Преглед изворни кода

fix(red-bag): 修复活动状态和红包类型逻辑错误

- 修正活动状态筛选器及显示的映射关系,支持未开始(0)、进行中(1)、已结束(2)三种状态
- 将红包类型选择由单选改为多选,并添加与后端枚举值(0,1,2)的转换逻辑
- 重构红包详情弹窗为组件内控制,优化搜索条件,增加用户ID、红包链接和时间范围查询
- 移除已废弃的详情弹窗外部控制逻辑,统一通过ref调用
ylong пре 2 дана
родитељ
комит
257039fb64

+ 14 - 10
src/views/marketing/redBag/components/red-bag-activity.vue

@@ -6,8 +6,10 @@
             <template #toolbar>
                 <div style="display: flex; align-items: center; gap: 10px">
                     <el-select v-model="activityStatus" placeholder="活动状态" clearable style="width: 250px">
+                        <!-- 0-未开始 1-进行中 2-已结束 -->
+                        <el-option label="未开始" :value="0" />
                         <el-option label="进行中" :value="1" />
-                        <el-option label="已结束" :value="0" />
+                        <el-option label="已结束" :value="2" />
                     </el-select>
                     <el-button type="primary" @click="reload()">查询</el-button>
                     <el-button type="primary" plain @click="reset">重置</el-button>
@@ -20,7 +22,7 @@
 
             <template #activityStatus="{ row }">
                 <el-tag :type="row.activityStatus === 1 ? 'success' : 'info'">
-                    {{ row.activityStatus === 1 ? '进行中' : '已结束' }}
+                    {{ activityStatusMap[row.activityStatus] }}
                 </el-tag>
             </template>
 
@@ -57,10 +59,7 @@
             </template>
         </el-dialog>
 
-        <!-- 红包码详情弹窗 -->
-        <el-dialog v-model="detailDialogVisible" title="红包码详情" width="1440px" :close-on-click-modal="false">
-            <red-bag-detail :activity-id="currentActivityId" />
-        </el-dialog>
+        <red-bag-detail ref="detailRef" />
     </div>
 </template>
 
@@ -80,6 +79,13 @@
         reload();
     };
 
+    // 活动状态映射
+    const activityStatusMap = {
+        0: '未开始',
+        1: '进行中',
+        2: '已结束'
+    };
+
     // 表格列配置
     const columns = ref([
         {
@@ -254,12 +260,10 @@
     };
 
     // 查看详情
-    const detailDialogVisible = ref(false);
-    const currentActivityId = ref(null);
+    const detailRef = ref(null);
 
     const handleDetail = (row) => {
-        currentActivityId.value = row.id;
-        detailDialogVisible.value = true;
+        detailRef.value?.open(row);
     };
 </script>
 

+ 67 - 70
src/views/marketing/redBag/components/red-bag-detail.vue

@@ -1,6 +1,13 @@
 <!-- 红包码详情列表 -->
 <template>
-    <div class="red-bag-detail">
+    <el-dialog
+        v-model="visible"
+        title="红包码详情"
+        width="1440px"
+        :close-on-click-modal="false"
+        destroy-on-close
+    >
+        <div class="red-bag-detail">
         <!-- 统计卡片 -->
         <div class="stats-row">
             <div class="stat-item">
@@ -47,47 +54,26 @@
 
         <!-- 搜索栏 -->
         <div style="display: flex; gap: 10px; align-items: center">
-            <el-input
-                v-model="searchForm.userName"
-                placeholder="用户名"
-                style="width: 200px"
-                clearable
-            />
-            <el-select
-                v-model="searchForm.redType"
-                placeholder="红包类型"
-                clearable
-                style="width: 150px"
-            >
-                <el-option label="无门槛" :value="0" />
-                <el-option label="现金" :value="1" />
-            </el-select>
-            <el-select
-                v-model="searchForm.drawStatus"
-                placeholder="领取状态"
-                clearable
-                style="width: 150px"
-            >
+            <el-input v-model="searchForm.userId" placeholder="用户ID" style="width: 200px" clearable />
+
+            <el-input v-model="searchForm.redLink" placeholder="红包链接" style="width: 200px" clearable />
+
+            <el-select v-model="searchForm.drawStatus" placeholder="领取状态" clearable style="width: 150px">
                 <el-option label="未领取" :value="0" />
                 <el-option label="已领取" :value="1" />
             </el-select>
+            <el-date-picker v-model="searchForm.drawTimeRange" type="datetimerange" range-separator="至"
+                start-placeholder="领取开始时间" end-placeholder="领取结束时间" style="max-width: 360px" clearable  />
             <el-button type="primary" @click="reload()">查询</el-button>
-            <el-button type="primary" plain @click="resetSearch"
-                >重置</el-button
-            >
+            <el-button type="primary" plain @click="resetSearch">重置</el-button>
         </div>
 
         <!-- 表格 -->
-        <common-table
-            ref="pageRef"
-            :pageConfig="pageConfig"
-            :columns="columns"
-            :tools="false"
-            :body-style="{ padding: '0' }"
-        >
+        <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns" :tools="false"
+            :body-style="{ padding: '0' }">
             <template #redType="{ row }">
-                <el-tag :type="row.redType === 1 ? 'success' : 'primary'">
-                    {{ row.redType === 1 ? '现金' : '无门槛' }}
+                <el-tag :type="row.redType === 1 ? 'success' : 'primary'" v-if="row.redType">
+                    {{ redTypeMap[row.redType] }}
                 </el-tag>
             </template>
 
@@ -98,41 +84,37 @@
             </template>
 
             <template #action="{ row }">
-                <el-button
-                    link
-                    type="primary"
-                    v-permission="'marketing:redBag:shareDetail'"
-                    @click="handleShareDetail(row)"
-                >
+                <el-button link type="primary" v-permission="'marketing:redBag:shareDetail'"
+                    @click="handleShareDetail(row)">
                     [分享信息]
                 </el-button>
             </template>
         </common-table>
 
         <!-- 分享信息弹窗 -->
-        <el-dialog
-            v-model="shareDialogVisible"
-            title="分享信息"
-            width="800px"
-            :close-on-click-modal="false"
-        >
+        <el-dialog v-model="shareDialogVisible" title="分享信息" width="800px" :close-on-click-modal="false">
             <red-bag-share :red-id="currentRedId" />
         </el-dialog>
-    </div>
+        </div>
+    </el-dialog>
 </template>
 
 <script setup>
-    import { ref, reactive, watch } from 'vue';
+    import { ref, reactive } from 'vue';
+    import { ElMessage } from 'element-plus';
     import CommonTable from '@/components/CommonPage/CommonTable.vue';
     import RedBagShare from './red-bag-share.vue';
     import request from '@/utils/request';
+    const visible = ref(false);
+    const activityId = ref();
+
+    // 红包类型映射
+    const redTypeMap = {
+        0: '无门槛',
+        1: '现金',
+        2: '无门槛/现金'
+    };
 
-    const props = defineProps({
-        activityId: {
-            type: Number,
-            required: true
-        }
-    });
 
     // 统计数据
     const stats = ref({});
@@ -141,14 +123,16 @@
     const searchForm = ref({
         userName: '',
         redType: undefined,
-        drawStatus: undefined
+        drawStatus: undefined,
+        drawTimeRange: []
     });
 
     const resetSearch = () => {
         searchForm.value = {
             userName: '',
             redType: undefined,
-            drawStatus: undefined
+            drawStatus: undefined,
+            drawTimeRange: []
         };
         reload();
     };
@@ -239,9 +223,18 @@
 
     // 刷新表格
     function reload() {
+        const [drawTimeStartRaw, drawTimeEndRaw] =
+            searchForm.value.drawTimeRange || [];
         pageRef.value?.reload({
-            activityId: props.activityId,
-            ...searchForm.value
+            activityId: activityId.value,
+            ...searchForm.value,
+            drawTimeRange: undefined,
+            drawTimeStart: drawTimeStartRaw
+                ? new Date(drawTimeStartRaw).toISOString()
+                : undefined,
+            drawTimeEnd: drawTimeEndRaw
+                ? new Date(drawTimeEndRaw).toISOString()
+                : undefined
         });
     }
 
@@ -249,7 +242,7 @@
     const loadStats = () => {
         request
             .get('/activity/red/bag/detail/activity/redBag/detail/sum', {
-                params: { activityId: props.activityId }
+                params: { activityId: activityId.value }
             })
             .then((res) => {
                 if (res.data.code === 200) {
@@ -258,17 +251,17 @@
             });
     };
 
-    // 监听 activityId 变化
-    watch(
-        () => props.activityId,
-        (newVal) => {
-            if (newVal) {
-                loadStats();
-                reload();
-            }
-        },
-        { immediate: true }
-    );
+    const open = (row) => {
+        const id = row?.id ?? row?.activityId;
+        if (!id) {
+            ElMessage.error('活动ID缺失,无法查看数据');
+            return;
+        }
+        activityId.value = id;
+        resetSearch();
+        loadStats();
+        visible.value = true;
+    };
 
     // 分享信息相关
     const shareDialogVisible = ref(false);
@@ -278,6 +271,10 @@
         currentRedId.value = row.id;
         shareDialogVisible.value = true;
     };
+
+    defineExpose({
+        open
+    });
 </script>
 
 <style lang="scss" scoped>

+ 30 - 9
src/views/marketing/redBag/components/red-bag-rule.vue

@@ -49,10 +49,10 @@
                 </el-form-item>
 
                 <el-form-item label="红包类型" prop="redType">
-                    <el-radio-group v-model="formData.redType">
-                        <el-radio :label="0">无门槛红包</el-radio>
-                        <el-radio :label="1">现金红包</el-radio>
-                    </el-radio-group>
+                    <el-checkbox-group v-model="formData.redType">
+                        <el-checkbox :value="0">无门槛红包</el-checkbox>
+                        <el-checkbox :value="1">现金红包</el-checkbox>
+                    </el-checkbox-group>
                 </el-form-item>
 
                 <el-form-item label="现金红包占比" prop="cashRate">
@@ -244,7 +244,7 @@
         scanNum: null,
         shareNum: null,
         sharedGetLimit: null,
-        redType: null,
+        redType: [],
         cashRate: null,
         redMinPrice: null,
         redMaxPrice: null,
@@ -270,10 +270,31 @@
             { required: true, message: '请输入分享次数', trigger: 'blur' }
         ],
         redType: [
-            { required: true, message: '请选择红包类型', trigger: 'change' }
+            {
+                type: 'array',
+                required: true,
+                min: 1,
+                message: '请选择红包类型',
+                trigger: 'change'
+            }
         ]
     };
 
+    const toRedTypeList = (redType) => {
+        if (redType === 2) return [0, 1];
+        if (redType === 0 || redType === 1) return [redType];
+        return [];
+    };
+
+    const toRedTypeValue = (redTypeList = []) => {
+        const hasZero = redTypeList.includes(0);
+        const hasOne = redTypeList.includes(1);
+        if (hasZero && hasOne) return 2;
+        if (hasOne) return 1;
+        if (hasZero) return 0;
+        return null;
+    };
+
     // 加载配置
     const loadConfig = async () => {
         try {
@@ -288,8 +309,7 @@
                         scanNum: data.scanNum || null,
                         shareNum: data.shareNum || null,
                         sharedGetLimit: data.sharedGetLimit || null,
-                        redType:
-                            data.redType !== undefined ? data.redType : null,
+                        redType: toRedTypeList(data.redType),
                         cashRate: data.cashRate || null,
                         redMinPrice: data.redMinPrice || null,
                         redMaxPrice: data.redMaxPrice || null,
@@ -327,7 +347,8 @@
             submitLoading.value = true;
             try {
                 const submitData = {
-                    ...formData.value
+                    ...formData.value,
+                    redType: toRedTypeValue(formData.value.redType)
                 };
 
                 const res = await request.post(