Kaynağa Gözat

抽奖活动模块新增页面及组件

DELL 3 yıl önce
ebeveyn
işleme
6ed39f2e74

+ 12 - 0
src/api/business/marketing.js

@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+
+//添加、修改
+export function addMarketing(data) {
+  return request({
+    url: `/api/v1/mp/admin/marketing/${data.id ? 'update' : 'create'}`,
+    method: 'post',
+    data
+  })
+}
+
+

+ 281 - 5
src/views/business/marketing/add.vue

@@ -1,17 +1,293 @@
 <template>
-  <div>1111
+  <div class="app-container goods-add">
+    <el-divider content-position="left">基础信息</el-divider>
+    <el-form ref="addItem" :rules="rules" :model="addData" label-width="120px">
+      <el-row :gutter="40" style="width: 600px">
+        <el-col :span="23">
+          <el-form-item label="活动名称:" prop="title">
+            <el-input v-model="addData.title" placeholder="输入活动名称" :readonly="readonly"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="23">
+          <!--          <el-form-item label="活动封面:" prop="picUrl">-->
+          <!--            <Upload v-model="addData.picUrl" :limit="1" />-->
+          <!--          </el-form-item>-->
+          <el-form-item label="活动封面:" prop="picUrl">
+            <image-upload
+              v-model="marketingPicUrl"
+              :limit="1"
+              :file-size="0.2"
+              @change="$refs.addItem.validateField(['picUrl'])"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col>
+          <el-form-item label="活动日期:" prop="dateValue">
+            <el-date-picker value-format="timestamp" v-model="addData.dateValue" type="datetimerange"
+                            range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="16">
+          <el-form-item label="初始用户数:">
+            <el-input v-model="addData.fakeNum" :readonly="readonly"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="23">
+          <el-form-item label="抽奖码获取方式:" prop="type">
+            <el-col>邀请用户助力</el-col>
+            <el-col>用户助力条件:
+              <el-radio-group v-model="labelRadio" :disabled="readonly">
+                <el-radio :label="1">每个账号终身仅助力一次</el-radio>
+                <el-radio :label="2" disabled>无</el-radio>
+              </el-radio-group>
+            </el-col>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-divider content-position="left">奖品设置</el-divider>
+      <el-row>
+        <el-col :span="22">
+          <el-form-item label="" prop="awardsList">
+            <!-- 奖级列表 -->
+            <awards-list ref="awards" v-model="awardsList" @handleCommand="handleCommand" @close="close"/>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-divider content-position="left">活动详情</el-divider>
+      <el-row>
+        <el-col :span="22">
+          <el-form-item label="" prop="description">
+            <wang-editor ref="editor" v-model="addData.description"/>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
 
-  222
-  </div>
+    <el-row>
+      <el-col :span="24" style="text-align: center">
+        <el-button type="info" @click="$router.replace('/marketing/marketing')">取消</el-button>
+        <el-button type="primary" @click="update()">保存</el-button>
+      </el-col>
+    </el-row>
 
+    <!-- 添加商品 -->
+    <goods-add :dialog-visible="goodsTableVisible" @close="close" @confirmGoods="confirmGoods"
+               v-if="goodsTableVisible"/>
+    <!-- 添加券 -->
+    <coupon-add :dialog-visible="couponTableVisible" @close="close" @confirmCoupon="confirmCoupon"
+                v-if="couponTableVisible"/>
+    <!-- 添加券包 -->
+    <coupon-pkg-add :dialog-visible="couponPkgTableVisible" @close="close" @confirmCouponPkg="confirmCouponPkg"
+                    v-if="couponPkgTableVisible"/>
+    <!-- 添加盲豆 -->
+    <coin-add :dialog-visible="coinTableVisible" @close="close" @confirmCoin="confirmCoin" v-if="coinTableVisible"/>
+  </div>
 </template>
 
 <script>
+import {getGoodsDetail, addMarketing} from '@/api/business/marketing'
+import Upload from '@/components/DragImageUpload'
+import WangEditor from '@/components/WangEditor'
+import AwardsList from "./components/AwardsList"
+import GoodsAdd from "./components/GoodsAdd"
+import CouponAdd from "./components/CouponAdd"
+import CouponPkgAdd from "./components/CouponPkgAdd"
+import CoinAdd from "./components/CoinAdd"
+
 export default {
-  name: "add"
+  name: "add",
+  components: {
+    Upload,
+    WangEditor,
+    AwardsList,
+    GoodsAdd,
+    CouponAdd,
+    CouponPkgAdd,
+    CoinAdd,
+  },
+  computed: {
+    marketingPicUrl: {
+      get() {
+        return this.addData.picUrl ? this.addData.picUrl.split(',').map(item => {
+          return {
+            fileName: item
+          }
+        }) : []
+      },
+      set(val) {
+        this.$set(this.addData, 'picUrl', val.map(item => {
+          return item.fileName
+        }).toString())
+      }
+    },
+  },
+  data() {
+    return {
+      addData: {
+        picUrl: '',//活动主图
+        startTime: '',//开始时间
+        endTime: '',//结束时间
+        fakeNum: 0,//初始用户数
+        description: '',//活动详情
+        awardsList: [],//奖级列表
+      },
+      labelRadio: 1,//单选框
+      rules: {
+        title: [{required: true, message: '请输入活动名称', trigger: 'blur'}],
+        picUrl: [{required: true, message: '请上传活动封面', trigger: 'change'}],
+        dateValue: [{required: true, message: '请设置活动日期', trigger: 'change'}]
+      },
+      readonly: this.$route.name === 'MarketingQuery',
+      // 奖级列表
+      awardsList: [],
+      goodsTableVisible: false, // 添加商品弹框
+      couponTitle: "", // 券名称
+      couponTableVisible: false, // 添加卡券弹框
+      couponPkgTableVisible: false, // 添加券包弹框
+      coinTableVisible: false, // 添加盲豆弹框
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      dateValue: [],//开始与结束日期
+    }
+  },
+  methods: {
+    // 保存
+    update() {
+      this.$refs.addItem.validate((valid, items) => {
+        if (valid) {
+          if(this.awardsList.length < 2) {
+            this.msgError('请至少设置两个奖级的的奖品!')
+            return;
+          }
+          console.log(this.awardsList)
+          // 判断没有设置奖品的奖级
+          let prizeIndex = this.awardsList.findIndex((item) => {
+            return !item.prizeList.length;
+          });
+
+          if (prizeIndex != -1) {
+            this.$message.error(
+              `请至少设置两个奖级的的奖品!`
+            );
+            return;
+          }
+          // 判断内定名额大于奖品名额
+          let quantityIndex = this.awardsList.findIndex((item) => {
+            console.log(item)
+            return item.insideNum > item.quantity;
+          });
+          if (quantityIndex != -1) {
+            this.$message.error(
+              `${this.awardsList[quantityIndex].name}的内定名额大于奖品名额,请重新设置!`
+            );
+            return;
+          }
+
+          this.awardsList.forEach((item) => {
+            item.prizeList = item.prizeList.map((ele) => {
+              return {
+                ...ele,
+                refId: ele.goodsId || ele.couponId || ele.id,
+                prizeType: ele.prizeType,
+                quantity: ele.quantity,
+                value: Number(ele.coinValue),
+              };
+            });
+          });
+
+          const { fakeNum, description, title, picUrl } = this.addData
+          addMarketing({
+            title,
+            description: encodeURI(description),
+            fakeNum,
+            startTime: this.addData.dateValue[1],
+            endTime: this.addData.dateValue[0],
+            awardsList: this.awardsList,
+            picUrl,
+          }).then(res => {
+            if (res.code === 0) {
+              this.$message({
+                message: this.addData.id ? '修改成功!' : '添加成功!',
+                type: 'success'
+              })
+              this.$store.dispatch('marketing/marketing', this.$route)
+              this.$router.go(-1)
+            }
+          })
+        } else {
+          if (items && Object.keys(items).length > 0) {
+            this.$message({
+              message: items[Object.keys(items)[0]][0].message,
+              type: 'warning'
+            })
+          }
+        }
+      })
+    },
+
+    // 添加奖品种类
+    handleCommand(e) {
+      if (e == "goods") {
+        this.goodsTableVisible = true;
+      } else if (e == "coupon") {
+        this.couponTableVisible = true;
+      } else if (e == "coupon_pkg") {
+        this.couponPkgTableVisible = true;
+      } else if (e == "coin") {
+        this.coinTableVisible = true;
+      }
+    },
+
+    // 关闭弹框
+    close() {
+      this.goodsTableVisible = false;
+      this.couponTableVisible = false;
+      this.couponPkgTableVisible = false;
+      this.coinTableVisible = false;
+    },
+
+    // 确认选中商品
+    confirmGoods(arr) {
+      this.$refs.awards.add(1, arr)
+    },
+
+    // 确认选中卡券
+    confirmCoupon(arr) {
+      ;
+      this.$refs.awards.add(1, arr)
+    },
+
+    // 确认选中券包
+    confirmCouponPkg(arr) {
+      ;
+      this.$refs.awards.add(1, arr)
+    },
+
+    // 确认输入盲豆
+    confirmCoin(obj) {
+      this.$refs.awards.add(2, obj)
+    },
+
+  }
 }
 </script>
 
-<style scoped>
+<style scoped lang="scss">
+.goods-add {
+  .tip {
+    font-size: 12px;
+    color: #999;
+  }
 
+  .el-divider {
+    .is-left {
+      color: #409EFF;
+      font-size: 20px;
+      font-weight: bolder;
+      left: 10px;
+    }
+  }
+}
 </style>

+ 146 - 0
src/views/business/marketing/components/ActivityTable.vue

@@ -0,0 +1,146 @@
+<template>
+  <div>
+    <el-dialog
+      title="添加券"
+      width="1000px"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+    >
+      <div class="dialog-search">
+        <div>参与用户数量:{{}}</div>
+        <div class="ge"></div>
+        <div>抽奖码数量:{{}}</div>
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="couponList"
+        @selection-change="handleSelectionCoupon"
+        class="el-table"
+      >
+        <el-table-column label="用户编号" prop="couponId" min-width="80" />
+        <el-table-column label="用户昵称" prop="title" min-width="80" />
+        <el-table-column label="抽奖码" prop="title" min-width="80" />
+        <el-table-column label="抽奖码获取时间" min-width="85">
+          <template slot-scope="scope">
+            <div>{{ scope.row.type.desc }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="奖级" prop="title" min-width="50" />
+        <el-table-column label="奖品名称" prop="title" min-width="85" />
+      </el-table>
+      <pagination
+        v-show="couponTotal > 0"
+        :total="couponTotal"
+        :page.sync="pageParams.pageNum"
+        :limit.sync="pageParams.pageSize"
+        @pagination="getCouponList"
+      />
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 关 闭 </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import { getCouponList } from "@/api/business/coupon";
+export default {
+  name: "CouponAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+    ids: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      couponTitle: "", // 券名称
+      couponList: [], // 卡券列表
+      couponTotal: 0, // 卡券总数
+      selectCouponList: [], // 选中卡券
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+    };
+  },
+  created() {
+    this.getCouponList();
+  },
+  methods: {
+    // 卡券列表
+    getCouponList() {
+      this.loading = true;
+      getCouponList(
+        "pageNum=" +
+        this.pageParams.pageNum +
+        "&pageSize=" +
+        this.pageParams.pageSize +
+        "&",
+        { title: this.couponTitle, status: "on", excludeCouponIds: this.ids }
+      ).then((res) => {
+        this.couponList = res.rows.map((item) => {
+          return {
+            ...item,
+            type: JSON.parse(item.type),
+            useArea: JSON.parse(item.useArea),
+            picUrl: publicFileGetUrl + item.picUrl,
+          };
+        });
+        this.couponTotal = res.total;
+        this.loading = false;
+      });
+    },
+
+    // 选中卡券
+    handleSelectionCoupon(e) {
+      this.selectCouponList = e.map((item) => {
+        return {
+          couponNum: 1,
+          couponId: item.couponId,
+          title: item.title,
+          createdTime: item.createdTime,
+          updatedTime: item.updatedTime,
+          type: item.type,
+          discount: item.discount,
+          dueDays: item.dueDays
+        };
+      });
+    },
+
+    // 确认选中卡券
+    confirmCoupon() {
+      this.$emit("confirmCoupon", this.selectCouponList);
+      this.close()
+    },
+
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.dialog-search {
+  display: flex;
+  line-height: 32px;
+  margin-bottom: 20px;
+  .ge {
+    width: 40px;
+  }
+}
+.dialog-btn {
+  display: flex;
+  align-content: center;
+  justify-content: flex-end;
+  padding: 40px 0 0;
+  .ge {
+    width: 40px;
+  }
+}
+</style>

+ 224 - 0
src/views/business/marketing/components/AwardsList.vue

@@ -0,0 +1,224 @@
+<template>
+  <div>
+    <div class="prize" v-for="(item, index) in awardsList" :key="index">
+        <div class="prize-top">
+          <div>奖级:{{ item.name }}</div>
+          <div>名额:
+            <el-input-number
+              v-model="item.quantity"
+              controls-position="right"
+              @change="handleChangeAllTwo($event, item)"
+              :min="0"
+              size="small"
+              :disabled="item.isEdit"
+            ></el-input-number>
+          </div>
+          <div>
+            内部名额:
+            <el-input-number
+              v-model="item.insideNum"
+              controls-position="right"
+              @change="handleChangeAll($event, item)"
+              :min="0"
+              size="small"
+              :disabled="item.isEdit"
+            ></el-input-number>
+          </div>
+        </div>
+        <div class="prize-table">
+          <el-table :data="item.prizeList" class="el-table">
+            <el-table-column label="奖品图片">
+              <template slot-scope="scope">
+                <el-image
+                  style="width: 70px; height: 70px"
+                  :src="scope.row.picUrl"
+                  :preview-src-list="[scope.row.picUrl]"
+                >
+                </el-image>
+              </template>
+            </el-table-column>
+            <el-table-column label="奖品名称" prop="title" />
+            <el-table-column label="奖品类型">
+              <template slot-scope="scope">
+                <div v-if="scope.row.prizeType == 'goods'">商品</div>
+                <div v-if="scope.row.prizeType == 'coupon'">券</div>
+                <div v-if="scope.row.prizeType == 'coupon_pkg'">券包</div>
+                <div v-if="scope.row.prizeType == 'coin'">盲豆</div>
+              </template>
+            </el-table-column>
+            <el-table-column label="排序" prop="sortWeight">
+              <template slot-scope="scope">
+                <div>
+                  <el-input-number
+                    v-model="scope.row.sortWeight"
+                    controls-position="right"
+                    :min="0"
+                    size="small"
+                  ></el-input-number>
+                </div>
+              </template>
+            </el-table-column>
+
+            <el-table-column label="操作" align="center">
+              <template slot-scope="scope">
+                <el-button
+                  size="mini"
+                  type="text"
+                  @click="handleDel(scope.$index, item)"
+                  >删除</el-button
+                >
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div class="prize-btn">
+          <el-dropdown @command="handleCommand($event, index)">
+            <el-button type="primary" size="small">
+              添加奖品<i class="el-icon-arrow-down el-icon--right"></i>
+            </el-button>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item command="goods">商品</el-dropdown-item>
+              <el-dropdown-item command="coupon">券</el-dropdown-item>
+              <el-dropdown-item command="coupon_pkg">券包</el-dropdown-item>
+              <el-dropdown-item command="coin">盲豆</el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </div>
+      </div>
+  </div>
+</template>
+<script>
+export default {
+  name: "AwardList",
+  props: {
+    value: {
+      type: Array,
+      default: () => []
+    },
+  },
+  data() {
+    return {
+      prizeIndex: null, // 奖级下标
+      // 奖级列表
+      awardsList: [
+        {
+          name: "一等奖",
+          sort: 1,
+          quantity: 0,
+          prizeList: [],
+          insideNum: 0,
+        },
+        {
+          name: "二等奖",
+          sort: 2,
+          quantity: 0,
+          prizeList: [],
+          insideNum: 0,
+        },
+        {
+          name: "三等奖",
+          sort: 3,
+          quantity: 0,//名额数量
+          prizeList: [],//列表
+          insideNum: 0,//内定数量
+        },
+        {
+          name: "四等奖",
+          sort: 4,
+          quantity: 0,//名额数量
+          prizeList: [],//列表
+          insideNum: 0,//内定数量
+        },
+        {
+          name: "五等奖",
+          sort: 5,
+          quantity: 0,//名额数量
+          prizeList: [],//列表
+          insideNum: 0,//内定数量
+        }
+      ],
+    };
+  },
+  methods: {
+    // 添加奖品
+    add(type, item) {
+      if(type == 1) {
+        this.awardsList[this.prizeIndex].prizeList = this.awardsList[this.prizeIndex].prizeList.concat(item);
+      } else if (type == 2) {
+        this.awardsList[this.prizeIndex].prizeList.push(item);
+      } else if (type == 3) {
+        this.awardsList = item
+      }
+      let filterArr = this.awardsList.filter((item) => {
+        return item.prizeList.length != 0;
+      });
+      this.$emit('input', filterArr)
+      this.$emit('close')
+    },
+    // 选择奖品种类
+    handleCommand(e, index) {
+      this.prizeIndex = index;
+      this.$emit('handleCommand', e)
+    },
+
+    // 改变奖级数量
+    handleChangeAll(e, item) {
+      this.$set(item, "insideNum", e);
+      this.$forceUpdate();
+    },
+    handleChangeAllTwo(e, item){
+      this.$set(item, "quantity", e);
+      this.$forceUpdate();
+    },
+
+    // 改变奖品数量
+    handleChange(e, index) {
+      this.prizeIndex = index;
+      this.$forceUpdate();
+      // this.getQuantity();
+    },
+
+    // 奖级商品删除
+    handleDel(index, item) {
+      this.prizeIndex = item.sort - 1;
+      let list = item.prizeList;
+      list.splice(index, 1);
+      this.$set(item, "prizeList", list);
+      // this.getQuantity();
+    },
+
+    // 计算奖级数量
+    getQuantity() {
+      let num = 0;
+      this.awardsList[this.prizeIndex].prizeList.forEach((item) => {
+        num += item.quantity;
+      });
+      this.awardsList[this.prizeIndex].quantity = num;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.prize {
+  width: 1000px;
+  margin-bottom: 50px;
+  background: #f9f9f9;
+  border: 1px solid #bbbbbb;
+  font-size: 14px;
+  &-top {
+    padding: 10px 20px;
+    margin-bottom: 10px;
+    display: flex;
+    align-content: center;
+    justify-content: space-around;
+    border-bottom: 1px solid #bbbbbb;
+    div {
+      line-height: 36px;
+    }
+  }
+  &-btn {
+    border-top: 1px solid #bbbbbb;
+    padding: 10px;
+  }
+}
+</style>

+ 94 - 0
src/views/business/marketing/components/CoinAdd.vue

@@ -0,0 +1,94 @@
+<template>
+  <div>
+    <el-dialog
+      title="添加盲豆奖品"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+      width="500px"
+    >
+      <el-form
+        :model="coinForm"
+        :rules="coinRules"
+        ref="coinForm"
+        label-width="100px"
+      >
+        <el-form-item label="盲豆数量" prop="quantity">
+          <el-input
+            v-model="coinForm.quantity"
+            size="small"
+            placeholder="请输入盲豆数量"
+            style="width: 200px"
+          />
+        </el-form-item>
+      </el-form>
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 取 消 </el-button>
+        <div class="ge"></div>
+        <el-button type="primary" size="small" @click="confirmCoin">
+          确 认
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+export default {
+  name: "CoinAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      coinForm: { quantity: "" },
+      coinRules: {
+        quantity: [
+          { required: true, message: "请输入数量", trigger: "blur" },
+          {
+            pattern: /^([1-9]\d*)$/,
+            message: "请输入合法的数字",
+            trigger: ["blur", "change"],
+          },
+        ],
+      },
+    };
+  },
+  methods: {
+    // 确认输入盲豆
+    confirmCoin() {
+      let coin = {
+        prizeType: "coin",
+        // quantity: 1,
+        title: `盲豆 x${this.coinForm.quantity}`,
+        picUrl: publicFileGetUrl + "md.jpeg",
+        coinValue: this.coinForm.quantity,
+        sortWeight: 100
+      };
+      this.$refs["coinForm"].validate((valid) => {
+        if (valid) {
+          this.$emit("confirmCoin", coin);
+        } else {
+          return false;
+        }
+      });
+    },
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.dialog-btn {
+  display: flex;
+  align-content: center;
+  justify-content: flex-end;
+  padding: 40px 0 0;
+  .ge {
+    width: 40px;
+  }
+}
+</style>

+ 183 - 0
src/views/business/marketing/components/CouponAdd.vue

@@ -0,0 +1,183 @@
+<template>
+  <div>
+    <el-dialog
+      title="添加券奖品"
+      width="1000px"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+    >
+      <div class="dialog-search">
+        <div>券名称:</div>
+        <el-input
+          v-model="couponTitle"
+          placeholder="请输入券名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="getCouponList"
+        />
+        <div class="ge"></div>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="getCouponList"
+          >查询</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="couponList"
+        @selection-change="handleSelectionCoupon"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+        />
+        <!--  -->
+        <el-table-column label="券ID" prop="couponId" />
+        <el-table-column label="券图片">
+          <template slot-scope="scope">
+            <div>
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="scope.row.picUrl"
+                :preview-src-list="[scope.row.picUrl]"
+              >
+              </el-image>
+            </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="券名称" prop="title" min-width="85" />
+        <el-table-column label="使用场景" min-width="85">
+          <template slot-scope="scope">
+            <div>{{ scope.row.type.desc }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="券价格" min-width="85">
+          <template slot-scope="scope">
+            <div>¥{{ $numberFormat(scope.row.discount) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="有效期限" min-width="85">
+          <template slot-scope="scope">
+            <div>领取后{{ scope.row.dueDays }}天有效</div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="couponTotal > 0"
+        :total="couponTotal"
+        :page.sync="pageParams.pageNum"
+        :limit.sync="pageParams.pageSize"
+        @pagination="getCouponList"
+      />
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 取 消 </el-button>
+        <div class="ge"></div>
+        <el-button type="primary" size="small" @click="confirmCoupon">
+          确 认
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import { getCouponList } from "@/api/business/coupon";
+export default {
+  name: "CouponAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      couponTitle: "", // 券名称
+      couponList: [], // 卡券列表
+      couponTotal: 0, // 卡券总数
+      selectCouponList: [], // 选中卡券
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+    };
+  },
+  created() {
+    this.getCouponList();
+  },
+  methods: {
+    // 卡券列表
+    getCouponList() {
+      this.loading = true;
+      getCouponList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        { title: this.couponTitle, status: "on" }
+      ).then((res) => {
+        this.couponList = res.rows.map((item) => {
+          return {
+            ...item,
+            type: JSON.parse(item.type),
+            useArea: JSON.parse(item.useArea),
+            picUrl: publicFileGetUrl + item.picUrl,
+          };
+        });
+        this.couponTotal = res.total;
+        this.loading = false;
+      });
+    },
+
+    // 选中卡券
+    handleSelectionCoupon(e) {
+      this.selectCouponList = e.map((item) => {
+        return {
+          prizeType: "coupon",
+          // quantity: 1,
+          couponId: item.couponId,
+          picUrl: item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中卡券
+    confirmCoupon() {
+      this.$emit("confirmCoupon", this.selectCouponList);
+    },
+
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.dialog-search {
+  display: flex;
+  line-height: 32px;
+  margin-bottom: 20px;
+  .ge {
+    width: 40px;
+  }
+}
+.dialog-btn {
+  display: flex;
+  align-content: center;
+  justify-content: flex-end;
+  padding: 40px 0 0;
+  .ge {
+    width: 40px;
+  }
+}
+</style>

+ 154 - 0
src/views/business/marketing/components/CouponPkgAdd.vue

@@ -0,0 +1,154 @@
+<template>
+  <div>
+    <el-dialog
+      title="添加券包奖品"
+      width="1000px"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+    >
+      <div class="dialog-search">
+        <div>券名称:</div>
+        <el-input
+          v-model="title"
+          placeholder="请输入券包名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @keyup.enter.native="getCouponList"
+        />
+        <div class="ge"></div>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="getCouponList"
+          >查询</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="couponList"
+        @selection-change="handleSelectionCouponPkg"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+        />
+        <el-table-column label="券包编号" prop="id" />
+        <el-table-column label="券包名称" prop="title" min-width="85" />
+        <el-table-column label="优惠券数量" prop="couponNum" />
+        <el-table-column label="总面值" min-width="85">
+          <template slot-scope="scope">
+            <div>¥{{ $numberFormat(scope.row.facePrice) }}</div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="couponPkgTotal > 0"
+        :total="couponPkgTotal"
+        :page.sync="pageParams.pageNum"
+        :limit.sync="pageParams.pageSize"
+        @pagination="getCouponList"
+      />
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 取 消 </el-button>
+        <div class="ge"></div>
+        <el-button type="primary" size="small" @click="confirmCouponPkg">
+          确 认
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import { getCouponList } from "@/api/business/couponPkg";
+export default {
+  name: "CouponAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      title: "", // 券包名称
+      couponList: [], // 券包列表
+      couponPkgTotal: 0, // 券包总数
+      selectCouponPkgList: [], // 选中券包
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+    };
+  },
+  created() {
+    this.getCouponList();
+  },
+  methods: {
+    // 券包列表
+    getCouponList() {
+      this.loading = true;
+      getCouponList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        { title: this.title, status: 1 }
+      ).then((res) => {
+        this.couponList = res.rows
+        this.couponPkgTotal = res.total;
+        this.loading = false;
+      });
+    },
+
+    // 选中券包
+    handleSelectionCouponPkg(e) {
+      this.selectCouponPkgList = e.map((item) => {
+        return {
+          prizeType: "coupon_pkg",
+          // quantity: 1,
+          id: item.id,
+          picUrl: publicFileGetUrl + item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中券包
+    confirmCouponPkg() {
+      this.$emit("confirmCouponPkg", this.selectCouponPkgList);
+    },
+
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.dialog-search {
+  display: flex;
+  line-height: 32px;
+  margin-bottom: 20px;
+  .ge {
+    width: 40px;
+  }
+}
+.dialog-btn {
+  display: flex;
+  align-content: center;
+  justify-content: flex-end;
+  padding: 40px 0 0;
+  .ge {
+    width: 40px;
+  }
+}
+</style>

+ 183 - 0
src/views/business/marketing/components/GoodsAdd.vue

@@ -0,0 +1,183 @@
+<template>
+  <div>
+    <el-dialog
+      title="添加实物奖品"
+      width="1000px"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+    >
+      <div class="dialog-search">
+        <div>商品名称:</div>
+        <el-input
+          v-model="goodsTitle"
+          placeholder="请输入商品名称"
+          clearable
+          size="small"
+          style="width: 220px" @clear="queryParams.pageNum = 1;getGoodsList()"
+          @keyup.enter.native="queryParams.pageNum = 1;getGoodsList()"
+        />
+        <div style="margin-left: 20px">商品价格:</div>
+<!--        <el-input v-model="minValue" placeholder="最低价格" clearable @keyup.enter.native="pageParams.pageNum = 1;getList()" />-->
+        <el-input style="width: 220px" v-model="queryParams.minValue"  @clear="queryParams.pageNum = 1;getGoodsList()" placeholder="最低价格" clearable @keyup.enter.native="queryParams.pageNum = 1;getGoodsList()"/>
+        <div style="width: 20px;text-align: center">-</div>
+<!--        <el-input v-model="maxValue" placeholder="最高价格" clearable @keyup.enter.native="pageParams.pageNum = 1;getList()" />-->
+        <el-input style="width: 220px" v-model="queryParams.maxValue"  @clear="queryParams.pageNum = 1;getGoodsList()" placeholder="最高价格" clearable @keyup.enter.native="queryParams.pageNum = 1;getGoodsList()"/>
+
+        <div class="ge"></div>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="getGoodsList()"
+          >查询</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="goodsList"
+        @selection-change="handleSelectionGoods"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+        />
+        <el-table-column label="商品ID" prop="goodsId" />
+        <el-table-column label="商品图片">
+          <template slot-scope="{ row }">
+            <div v-if="row.picUrl">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="row.picUrl.split(',')[0]"
+                :preview-src-list="row.picUrl.split(',')"
+              >
+              </el-image>
+            </div>
+            <p v-else>-</p>
+          </template>
+        </el-table-column>
+        <el-table-column label="商品名称" prop="title" min-width="85" />
+
+        <el-table-column label="商品价格" min-width="85">
+          <template slot-scope="scope">
+            <div>¥{{ $numberFormat(scope.row.value) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="商品库存" prop="quantity" width="80" />
+      </el-table>
+      <pagination
+        v-show="goodsTotal > 0"
+        :total="goodsTotal"
+        :page.sync="pageParams.pageNum"
+        :limit.sync="pageParams.pageSize"
+        @pagination="getGoodsList"
+      />
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 取 消 </el-button>
+        <div class="ge"></div>
+        <el-button type="primary" size="small" @click="confirmGoods">
+          确 认
+        </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import { getGoodsList } from "@/api/business/goods";
+import { accMul } from '@/utils/util'
+export default {
+  name: "GoodsAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      goodsTitle: "", // 商品名称
+      queryParams:{},
+
+      goodsList: [], // 商品列表
+      goodsTotal: 0, // 商品总数
+      selectGoodsList: [], // 选中商品
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+    };
+  },
+  created() {
+    this.getGoodsList();
+  },
+  methods: {
+    // 商品列表
+    getGoodsList() {
+      this.loading = true;
+      getGoodsList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        { title: this.goodsTitle,  status: "on", minValue: this.queryParams.minValue?accMul(this.queryParams.minValue, 100):this.queryParams.minValue, maxValue: this.queryParams.maxValue?accMul(this.queryParams.maxValue, 100):this.queryParams.maxValue,}
+      ).then((res) => {
+        this.goodsList = res.rows.map((item) => {
+          return {
+            ...item,
+            picUrl: publicFileGetUrl + item.picUrl.split(",")[0],
+          };
+        });
+        this.goodsTotal = res.total;
+        this.loading = false;
+      });
+    },
+
+    // 选中商品
+    handleSelectionGoods(e) {
+      this.selectGoodsList = e.map((item) => {
+        return {
+          prizeType: "goods",
+          // quantity: 1,
+          goodsId: item.goodsId,
+          picUrl: item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中商品
+    confirmGoods() {
+      this.$emit("confirmGoods", this.selectGoodsList);
+    },
+
+    close() {
+      this.$emit("close");
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.dialog-search {
+  display: flex;
+  line-height: 32px;
+  margin-bottom: 20px;
+  .ge {
+    width: 20px;
+  }
+}
+.dialog-btn {
+  display: flex;
+  align-content: center;
+  justify-content: flex-end;
+  padding: 40px 0 0;
+  .ge {
+    width: 20px;
+  }
+}
+</style>

+ 10 - 5
src/views/business/marketing/index.vue

@@ -60,35 +60,40 @@
       <el-table-column label="状态" prop="status">
         <template slot-scope="{row}">
           <el-tag :type="JSON.parse(row.status).value === 'on' ? 'success' : 'info'">{{ JSON.parse(row.status).desc }}</el-tag>
-
         </template>
       </el-table-column>
       <el-table-column fixed="right" align="right" label="操作" width="240">
         <template slot-scope="{row}">
           <el-button v-hasPermi="['business:marketing:query']" type="text" @click="$router.push({ name: 'MarketingQuery', query: { id: row.couponId } })">查看</el-button>
           <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:marketing:edit']" type="text" @click="$router.push({ name: 'MarketingEdit', query: { id: row.couponId } })">编辑</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:marketing:edit']" type="text" @click="$router.push({ name: 'MarketingEdit', query: { id: row.couponId } })">活动数据</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:on']" type="text" @click="setStatus(row, 'on')">上架</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:coupon:off']" type="text" @click="setStatus(row, 'off')">下架</el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:marketing:edit']" type="text"  @click="activityTableVisible = true">活动数据</el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:on']" type="text" @click="setStatus(row, 'on')">开启</el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:coupon:off']" type="text" @click="setStatus(row, 'off')">关闭</el-button>
           <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:remove']" class="del" type="text" @click="del(row)">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
     <pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList()" />
+    <activity-table :dialog-visible="activityTableVisible"  @close="activityTableVisible = false" v-if="activityTableVisible"></activity-table>
   </div>
 </template>
 <script>
 import { getCouponList, delCoupon, setCouponStatus } from '@/api/business/coupon'
+import ActivityTable from "./components/ActivityTable";
 import { accDiv } from '@/utils/util'
 export default {
   name: 'CouponList',
+  components:{
+    ActivityTable,
+  },
   data() {
     return {
       loading: false,
       showSearch: true,
       tableData: [],
       queryParams: {},
-      total: 0
+      total: 0,
+      activityTableVisible: false,
     }
   },
   created() {