lsx 2 anni fa
parent
commit
9b1429eed0

+ 57 - 0
src/api/business/exchangeCode.js

@@ -0,0 +1,57 @@
+import request from '@/utils/request'
+
+// 查询分类列表, 支持翻页
+export function goodsExchangeList(urlParams, data) {
+  return request({
+    url: '/api/v1/mp/admin/CdKey/list',
+    method: 'post',
+    data,
+    urlParams
+  })
+}
+
+// 添加兑换码组
+export function goodsExchangeCreate(data) {
+  return request({
+    url: '/api/v1/mp/admin/CdKey/create',
+    method: 'post',
+    data
+  })
+}
+
+// 查询兑换码组详情
+export function getExchangeCode(data) {
+  return request({
+    url: `/api/v1/mp/admin/CdKey/detail/${data}`,
+    method: 'post',
+  })
+}
+
+// 查看兑换码详情
+export function getExchangeCodelist(urlParams, data) {
+  return request({
+    url: `/api/v1/mp/admin/CdKey/exchangeDetail/${data}`,
+    method: 'post',
+    urlParams
+  })
+}
+
+
+// 兑换码激活
+export function activateExchangeCode(data) {
+  return request({
+    url: `/api/v1/mp/admin/CdKey/activate`,
+    method: 'post',
+    data
+  })
+}
+
+// 导出
+export function exportCode(data) {
+  return request({
+    url: '/api/v1/mp/admin/CdKey/export',
+    method: 'post',
+    timeout: 15 * 60 * 1000,
+    data
+  })
+}

+ 19 - 0
src/router/index.js

@@ -192,6 +192,25 @@ export const constantRoutes = [
       }
     ],
   },
+  {
+    path: '/exchange',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: 'addCode',
+        component: (resolve) => require(['@/views/business/exchange/addCode'], resolve),
+        name: 'ExchangeAdd',
+        meta: { title: '添加兑换码', activeMenu: '/goods/exchange' }
+      },
+      {
+        path: 'detailCode',
+        component: (resolve) => require(['@/views/business/exchange/addCode'], resolve),
+        name: 'ExchangeAdd',
+        meta: { title: '查看兑换码', activeMenu: '/goods/exchange' }
+      }
+    ],
+  },
   {
     path: '/coupon',
     component: Layout,

+ 312 - 0
src/views/business/exchange/addCode.vue

@@ -0,0 +1,312 @@
+<template>
+  <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="10">
+        <el-form-item label="门店:" prop="channelId">
+          <el-select v-model="addData.channelId" placeholder="请选择门店" :disabled="id?true:false" style="width: 240px;" filterable :filter-method="dataFilter">
+            <el-option v-for="(item) in siteList" :key="item.channelId" :label="item.name" :value="item.channelId">
+              <div>
+                <span style="float: left;">{{item.name}} </span>
+                <span style="float: right;">{{item.mobile}}</span>
+              </div>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="7">
+            <el-form-item label="兑换码数量:" prop="quantity">
+            <el-input v-model="addData.quantity" placeholder="请输入兑换码数量" :disabled="id?true:false" style="width: 240px;" />
+          </el-form-item>
+          </el-col>
+          <el-col :span="6" v-if="id?true:false">
+            <div class="clk" @click="toCodelist()">
+              查看
+            </div>
+          </el-col>
+          
+        </el-row>
+        
+        <el-form-item label="有效期:" prop="validityPeriod">
+          <el-select v-model="addData.validityPeriod" placeholder="请选择有效期" :disabled="id?true:false" style="width: 240px;">
+            <el-option label="三个月" value="threeMoths"></el-option>
+            <el-option label="六个月" value="sixMonths"></el-option>
+            <el-option label="永久" value="forever"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-row>
+      <el-divider content-position="left">商品设置</el-divider>
+      <el-row :gutter="10">
+        <el-col :span="22">
+          <el-form-item label="" prop="goodsList">
+            <!-- 奖级列表 -->
+            <code-list ref="awards" :id="id?id:''" v-model="goodsList" @handleCommand="handleCommand" @close="close" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <el-row v-if="!id">
+      <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" />
+
+     <!--  查询兑换码 -->
+     <exchange-code-list v-if="exchangeCodeShow" @cancel="exchangeCodeShow = false" :exchangeCodeShow="exchangeCodeShow" :id="id"/>
+  </div>
+</template>
+
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import { getExchangeCode, goodsExchangeCreate } from '@/api/business/exchangeCode'
+import CodeList from "./components/CodeList"
+import GoodsAdd from "./components/GoodsAdd"
+import CouponAdd from "./components/CouponAdd"
+import CouponPkgAdd from "./components/CouponPkgAdd"
+import CoinAdd from "./components/CoinAdd"
+
+import ExchangeCodeList from "./components/ExchangeCodeList"
+import { listAllSaleSite } from "@/api/admin/salesite";
+export default {
+  name: 'ExchangeAdd',
+  components: {
+    CodeList,
+    GoodsAdd,
+    CouponAdd,
+    CouponPkgAdd,
+    CoinAdd,
+    ExchangeCodeList
+  },
+  data() {
+    return {
+      id: this.$route.query.id,
+      siteList: [],//门店列表
+      siteCopyList: [],//门店列表
+      addData: {
+        channelId: '',//门店
+        siteName: '',//门店名称
+        type: '',//
+        quantity: '',//数量
+        goodsList: [],//兑换码关联商品
+      },
+      rules: {
+        channelId: [{ required: true, message: '请选择门店', trigger: 'blur' }],
+        validityPeriod: [{ required: true, message: '请选择有效期', trigger: 'blur' }],
+        quantity: [
+          { required: true, message: "请输入兑换码", trigger: ["blur", "change"] },
+          { pattern: /^[1-9]\d*$/, message: "请输入正确的数字", trigger: ["blur", "change"]}]
+      },
+      // 列表
+      goodsList: [],
+      goodsTableVisible: false, // 添加商品弹框
+      couponTableVisible: false, // 添加卡券弹框
+      couponPkgTableVisible: false, // 添加券包弹框
+      coinTableVisible: false, // 添加盲豆弹框
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+
+      exchangeCodeShow: false,
+    }
+  },
+  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())
+      }
+    },
+  },
+  created() {
+    if (this.id) {
+      getExchangeCode(this.id).then(res => {
+        const { channelId, quantity, siteName, validityPeriod, goodsList, id } = res.data
+        this.addData = { channelId, quantity, siteName, validityPeriod: JSON.parse(validityPeriod).value, goodsList, id }
+        if (goodsList) {
+          goodsList.forEach((item) => {
+            item.type = item.type && JSON.parse(item.type).value
+            item.picUrl = publicFileGetUrl + item.picUrl.split(',')[0]
+          });
+          this.$nextTick(() => {
+            this.$refs.awards.add(3, goodsList)
+          })
+          this.goodsList = goodsList
+        }
+      })
+    }
+  },
+  mounted() {
+    this.getSaleSiteList()
+  },
+  methods: {
+    // 获取门店下拉列表
+    getSaleSiteList() {
+      listAllSaleSite({}).then(response => {
+        this.siteList = response.data || [];
+        this.siteCopyList = response.data || [];
+      });
+    },
+    dataFilter(val) {
+      if (val) { //val存在
+        this.siteList = this.siteCopyList.filter((item) => {
+          if (!!~item.mobile.indexOf(val) || !!~item.mobile.toUpperCase().indexOf(val.toUpperCase())
+            || !!~item.name.indexOf(val) || !!~item.name.indexOf(val)) {
+            return true
+          }
+        })
+      } else { //val为空时,还原数组
+        this.siteList = this.siteCopyList;
+      }
+    },
+    // 保存
+    update() {
+      this.$refs.addItem.validate((valid, items) => {
+        if (valid) {
+          if (this.goodsList.length < 1) {
+            this.msgError('请至少设置一个商品!')
+            return;
+          }
+          // 判断没有设置奖级数量
+          let prizeIndexThree = this.goodsList.findIndex((item) => {
+            return !item.quantity && item.quantity != 0;
+          });
+          if (prizeIndexThree != -1) {
+            this.$message.error(
+              `请设置"${this.goodsList[prizeIndexThree].title}"的数量!`
+            );
+            return;
+          }
+
+          this.goodsList = this.goodsList.map((item) => {
+            return {
+              ...item,
+              refId: item.refId || item.goodsId || item.couponId || item.id,
+            }
+          });
+
+          const { channelId, quantity, siteName, validityPeriod, } = this.addData
+          goodsExchangeCreate({
+            channelId,
+            quantity,
+            siteName,
+            validityPeriod,
+            goodsList: this.goodsList,
+            id: this.addData.id ? this.addData.id : "",
+          }).then(res => {
+            if (res.code === 0) {
+              this.$message({
+                message: this.addData.id ? '修改成功!' : '添加成功!',
+                type: 'success'
+              })
+              this.$store.dispatch('tagsView/delView', 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'
+            })
+          }
+        }
+      })
+    },
+
+    toCodelist() {
+      this.exchangeCodeShow = true
+    },
+
+
+    // 添加奖品种类
+    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 lang="scss">
+.goods-add {
+  .tip {
+    font-size: 12px;
+    color: #999;
+  }
+
+  .el-divider {
+    .is-left {
+      color: #409eff;
+      font-size: 20px;
+      font-weight: bolder;
+      left: 10px;
+    }
+  }
+}
+.clk {
+  display: inline-block;
+  line-height: 36px;
+  color: rgb(0, 114, 255);
+  font-size: 16px;
+  cursor: pointer;
+}
+.clk:hover {
+  color: rgb(64, 146, 255);
+}
+</style>

+ 151 - 0
src/views/business/exchange/components/CodeList.vue

@@ -0,0 +1,151 @@
+<template>
+  <div>
+    <div class="prize">
+      <div class="prize-table">
+        <el-table :data="goodsList" 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">
+            <template slot-scope="scope">
+              <div v-if="scope.row.type == 'coin' && scope.row.value >= 0">盲豆 x{{scope.row.value}}</div>
+              <div v-else>{{scope.row.title}}</div>
+            </template>
+          </el-table-column>
+          <el-table-column label="商品类型">
+            <template slot-scope="scope">
+              <div v-if="scope.row.type == 'goods'">商品</div>
+              <div v-if="scope.row.type == 'coupon'">券</div>
+              <div v-if="scope.row.type == 'coupon_pkg'">券包</div>
+              <div v-if="scope.row.type == 'coin'">盲豆</div>
+            </template>
+          </el-table-column>
+          <!-- 商品价格 -->
+          <!-- 商品成本 -->
+          <!-- 商品数量 -->
+          <el-table-column label="兑换码数量" prop="quantity" align="center">
+             <template slot-scope="scope">
+               <div>
+                 <el-input-number
+                   v-model="scope.row.quantity"
+                   controls-position="right"
+                   @change="handleChange($event)"
+                   :min="1"
+                   size="small"
+                   :disabled="id?true:false"
+                 ></el-input-number>
+               </div>
+             </template>
+           </el-table-column>
+          <el-table-column label="操作" align="center" v-if="!id">
+            <template slot-scope="scope">
+              <el-button size="mini" type="text" @click="handleDel(scope.$index)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="prize-btn" v-if="!id">
+        <el-dropdown @command="handleCommand($event)">
+          <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: {
+    id: {
+      type: [String,Number],
+      default: false,
+    },
+  },
+  data() {
+    return {
+      // 奖级列表
+      goodsList: [
+        // {
+        //   createTime: "",
+        //   groupId: 1,
+        //   id: 0,
+        //   isDeleted: 0,
+        //   picUrl: "",
+        //   quantity: 0,
+        //   refId: "",
+        //   title: "",
+        //   type: "",
+        //   updateTime: "",
+        //   value: 0,
+        // },
+      ],
+    };
+  },
+  methods: {
+    // 添加奖品
+    add(type, item) {
+      if (type == 1) {
+        item.forEach((res)=>{
+          this.goodsList = this.goodsList.concat(res);
+        })
+      } else if (type == 2) {
+        this.goodsList.push(item);
+      } else if (type == 3) {
+        this.goodsList = item
+      }
+      this.$emit('input', this.goodsList)
+      this.$emit('close')
+    },
+    // 选择奖品种类
+    handleCommand(e) {
+      this.$emit('handleCommand', e)
+    },
+
+    // 改变奖品数量
+    handleChange(e) {
+      this.$forceUpdate();
+    },
+
+    // 奖级商品删除
+    handleDel(index) {
+      this.goodsList.splice(index, 1);
+    },
+
+  },
+};
+</script>
+<style lang="scss" scoped>
+.prize {
+  width: 100%;
+  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/exchange/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 = {
+        type: "coin",
+        // quantity: 1,
+        title: `盲豆 x${this.coinForm.quantity}`,
+        picUrl: publicFileGetUrl + "md.jpeg",
+        value: 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>

+ 194 - 0
src/views/business/exchange/components/CouponAdd.vue

@@ -0,0 +1,194 @@
+<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"
+        row-key="couponId"
+        @selection-change="handleSelectionCoupon"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+          :reserve-selection="true"
+        />
+        <!--  -->
+        <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.channelSharedRate }}%</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 {
+          type: "coupon",
+          // quantity: 1,
+          couponId: item.couponId,
+          picUrl: item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中卡券
+    confirmCoupon() {
+      if(!this.selectCouponList.length) {
+        this.msgInfo('请选择券')
+        return
+      }
+      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>

+ 160 - 0
src/views/business/exchange/components/CouponPkgAdd.vue

@@ -0,0 +1,160 @@
+<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"
+        row-key="id"
+        @selection-change="handleSelectionCouponPkg"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+          :reserve-selection="true"
+        />
+        <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 {
+          type: "coupon_pkg",
+          // quantity: 1,
+          id: item.id,
+          picUrl: publicFileGetUrl + item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中券包
+    confirmCouponPkg() {
+      if(!this.selectCouponPkgList.length) {
+        this.msgInfo('请选择券包')
+        return
+      }
+      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>

+ 113 - 0
src/views/business/exchange/components/ExchangeCodeList.vue

@@ -0,0 +1,113 @@
+<template>
+  <div>
+    <el-dialog title="查看兑换码" :visible.sync="exchangeCodeShow" :before-close="close" width="55%">
+      <span class="span1">已兑数量:{{ cdList.length?cdList[0].cashedQty:'-' }}</span> <span class="span2">未兑数量:{{ cdList.length?cdList[0].remainQty:'-' }}</span>
+      <el-table :data="cdList" style="margin-top: 20px;">
+        <el-table-column property="keyId" label="兑换码Id" min-width="200" align="center"></el-table-column>
+        <el-table-column property="goodsName" label="商品名称" min-width="200" align="center">
+          <template slot-scope="scope">
+            <div v-if="scope.row.type && JSON.parse(scope.row.type).value == 'coin'">
+              {{ scope.row.goodsName + ' x' + scope.row.value }}
+            </div>
+            <div v-else>
+              {{ scope.row.goodsName }}
+            </div>
+          </template>
+        </el-table-column>
+        <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 property="cdKey" label="兑换码" min-width="200" align="center"></el-table-column>
+        <el-table-column property="status" label="状态" min-width="80" align="center">
+          <template slot-scope="{row}">
+            <div v-if="row.status == 1">
+              已兑换
+            </div>
+            <div v-else style="color: green; font-weight: 500; ">
+              未兑换
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination :total="total" :page.sync="pageParams.pageNum" :limit.sync="pageParams.pageSize" @pagination="getList()" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { publicFileGetUrl } from "@/api/common"
+import { getExchangeCodelist } from "@/api/business/exchangeCode";
+export default {
+  props: {
+    exchangeCodeShow: {
+      type: Boolean,
+      default: true
+    },
+    id: {
+      type: [Number, String],
+      default: 0
+    },
+  },
+  data() {
+    return {
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      loading: false,
+      cdList: [],
+      total: 0,
+    };
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    close() {
+      this.$emit('cancel')
+    },
+    getList() {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+      getExchangeCodelist('pageNum=' + this.pageParams.pageNum + '&pageSize=' + this.pageParams.pageSize + '&', this.id).then(res => {
+        this.loading = false
+        if (res.code === 0) {
+          res.rows.forEach(ele => {
+            ele.picUrl = publicFileGetUrl + ele.picUrl.split(',')[0]
+          });
+          this.cdList = res.rows
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.span1 {
+  font-size: #666;
+  display: inline-block;
+  position: absolute;
+  top: 60px;
+  font-size: 15px;
+  font-weight: 500;
+}
+.span2 {
+  font-size: #666;
+  display: inline-block;
+  position: absolute;
+  top: 60px;
+  left: 200px;
+  font-size: 15px;
+  font-weight: 500;
+}
+</style>

+ 189 - 0
src/views/business/exchange/components/GoodsAdd.vue

@@ -0,0 +1,189 @@
+<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"
+        row-key="goodsId"
+        @selection-change="handleSelectionGoods"
+        class="el-table"
+      >
+        <el-table-column
+          type="selection"
+          width="55"
+          align="center"
+          fixed="left"
+          :reserve-selection="true"
+        />
+        <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 {
+          type: "goods",
+          // quantity: 1,
+          goodsId: item.goodsId,
+          picUrl: item.picUrl,
+          title: item.title,
+          sortWeight: 100
+        };
+      });
+    },
+
+    // 确认选中商品
+    confirmGoods() {
+      if(!this.selectGoodsList.length) {
+        this.msgInfo('请选择商品')
+        return
+      }
+      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>

+ 318 - 0
src/views/business/exchange/index.vue

@@ -0,0 +1,318 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch">
+
+      <el-form-item label="创建日期">
+        <el-date-picker v-model="addTimeArr" type="datetimerange" size="small" value-format="timestamp" range-separator="至" start-placeholder="时间选择" end-placeholder="时间选择" @change="addTime">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="激活日期">
+        <el-date-picker v-model="activationTimeArr" type="datetimerange" size="small" value-format="timestamp" range-separator="至" start-placeholder="时间选择" end-placeholder="时间选择" @change="activationTime">
+        </el-date-picker>
+      </el-form-item>
+      <br>
+      <el-form-item label="兑换码数量" prop="minValue">
+        <el-input v-model="queryParams.minCdKeyNum" placeholder="最小值" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+      </el-form-item>
+      <el-form-item label="-" prop="maxValue">
+        <el-input v-model="queryParams.maxCdKeyNum" placeholder="最大值" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+      </el-form-item>
+
+      <el-form-item label="门店" prop="channelId">
+        <el-select v-model="queryParams.channelId" placeholder="请选择门店" style="width: 100%;" filterable clearable :filter-method="dataFilter" @change="pageParams.pageNum = 1;handleQuery()">
+          <el-option v-for="(item) in siteList" :key="item.channelId" :label="item.name" :value="item.channelId">
+            <div>
+              <span style="float: left;">{{item.name}} </span>
+              <span style="float: right;">{{item.mobile}}</span>
+            </div>
+          </el-option>
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="状态">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable @change="queryParams.pageNum = 1;getList()">
+          <el-option :label="item.dictLabel" :value="item.dictValue" v-for="(item, index) in statusList" :key="index" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="getList(true)">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" icon="el-icon-plus" size="mini" @click="$router.push({ path: '/exchange/addCode' })" v-hasPermi="['business:exchange:add']">创建兑换码</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-printer"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['business:exchange:export']"
+          >导出兑换码</el-button
+        >
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList()"></right-toolbar>
+    </el-row>
+    <!-- 列表 -->
+    <el-table ref="table" @select="handleSelect" v-loading="loading" :data="list" class="ticket-table">
+      <el-table-column type="selection" width="55" align="center" fixed="left" />
+      <el-table-column label="兑换码编号" prop="groupId" />
+      <el-table-column label="兑换码数量" prop="quantity" />
+      <el-table-column label="门店名称" prop="siteName" />
+      <el-table-column label="创建日期" prop="createdTime">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.createdTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="激活日期" prop="activeTime">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.activeTime) }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" prop="status" align="center">
+        <template slot-scope="{ row }">
+          <el-tag type="warning" v-if="row.status && JSON.parse(row.status).value == 'waiting'">待生成</el-tag>
+          <el-tag type="success" v-if="row.status && JSON.parse(row.status).value == 'nonactivated'">未激活</el-tag>
+          <el-tag type="" v-if="row.status && JSON.parse(row.status).value == 'activated'">已生效</el-tag>
+          <el-tag type="info" v-if="row.status && JSON.parse(row.status).value == 'invalid'">已失效</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center">
+        <template slot-scope="{ row }">
+          <div>
+            <el-button v-hasPermi="['business:exchange:detail']" type="text" @click="$router.push({ path: '/exchange/detailCode',query: {id: row.groupId} })">查看</el-button>
+            <el-button v-if="row.status && JSON.parse(row.status).value == 'nonactivated'" v-hasPermi="['business:exchange:edit']" type="text" @click="setStatus(row)">激活</el-button>
+          </div>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination v-show="total > 0" :total="total" :page.sync="pageParams.pageNum" :limit.sync="pageParams.pageSize" @pagination="getList" />
+
+    <add-code v-if="exchangeShow" :dialog-show="exchangeShow" @close="close" />
+  </div>
+</template>
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import {
+  goodsExchangeList,
+  activateExchangeCode,exportCode,
+} from "@/api/business/exchangeCode";
+import { listAllSaleSite } from "@/api/admin/salesite";
+import AddCode from "./components/addCode.vue";
+export default {
+  name: "ExchangeCode",
+  components: {
+    AddCode,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      exportLoading: false,
+      queryParams: {},
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      // 总条数
+      total: 0,
+      list: [],
+      exchangeShow: false,
+
+      addTimeArr: [],// 添加时间
+      activationTimeArr: [],//激活时间
+      siteList: [],//门店列表
+      siteCopyList: [],//门店列表
+      statusList: [],//状态下拉选项
+      ids: null,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  mounted() {
+    this.getSaleSiteList()
+    this.getCodeStatus()
+  },
+  methods: {
+    /** 查询字典类型详细 */
+    getCodeStatus() {
+      this.getDicts('cd_key_status').then(res => {
+        this.statusList = res.data
+      })
+    },
+    // 获取门店下拉列表
+    getSaleSiteList() {
+      listAllSaleSite({}).then(response => {
+        this.siteList = response.data || [];
+        this.siteCopyList = response.data || [];
+      });
+    },
+    dataFilter(val) {
+      if (val) { //val存在
+        this.siteList = this.siteCopyList.filter((item) => {
+          if (!!~item.mobile.indexOf(val) || !!~item.mobile.toUpperCase().indexOf(val.toUpperCase())
+            || !!~item.name.indexOf(val) || !!~item.name.indexOf(val)) {
+            return true
+          }
+        })
+      } else { //val为空时,还原数组
+        this.siteList = this.siteCopyList;
+      }
+    },
+    getList() {
+      this.loading = true;
+      goodsExchangeList("pageNum=" +this.pageParams.pageNum +"&pageSize=" +this.pageParams.pageSize +"&",this.queryParams).then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            this.total = res.total;
+            this.list = res.rows;
+            console.log('list',list)
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    //搜索
+    handleQuery() {
+      this.siteList = this.siteCopyList;
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    // 重置
+    resetQuery() {
+      this.pageParams.pageNum = 1
+      this.addTimeArr = [];
+      this.getList();
+    },
+
+    //查看详情
+    toDetail() {
+
+    },
+
+    //激活兑换码
+    setStatus(item) {
+      this.$confirm(
+        `确认激活兑换码 “${item.groupId}” 吗?`,
+        `激活兑换码`,
+        {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        }
+      ).then(() => {
+        let data = {
+        groupId: item.groupId,
+        isActive: 1,
+      }
+      activateExchangeCode(data).then((res) => {
+          if (res.code === 0) {
+            this.$message.success("激活成功!");
+            this.getList();
+          }
+        });
+      });
+    },
+
+    //勾选Checkbox时的处理
+    handleSelect(selection, row) {
+      const isSelect = selection.find((item) => item.groupId === row.groupId);
+      this.$refs.table.clearSelection();
+      if (isSelect) {
+        this.$refs.table.toggleRowSelection(row, true);
+        this.ids = row.groupId;
+      } else {
+        this.ids = "";
+      }
+    },
+
+    /** 导出按钮操作 */
+    handleExport() {
+      const groupId = this.ids || [];
+
+      if (groupId.length == 0) {
+        this.$alert("请选择你要导出的兑换码组!", "提示", { type: "warning" });
+      } else {
+        this.$confirm("是否确认导出所选兑换码组?", "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            this.vloading = this.$loading({
+              lock: true,
+              text: "正在导出.....",
+              background: "rgba(0, 0, 0, 0.7)",
+            });
+            return exportCode({ groupIdList:[groupId] });
+          })
+          .then((response) => {
+            this.vloading.close();
+            this.download(response.msg);
+            this.exportLoading = false;
+          })
+          .catch(() => {
+            this.vloading.close();
+            this.exportLoading = false;
+          });
+      }
+    },
+
+    // 选择创建时间
+    addTime(e) {
+      if (e) {
+        this.queryParams.createTimeStart = e[0];
+        this.queryParams.createTimeEnd = e[1];
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      } else {
+        this.queryParams.createTimeStart = "";
+        this.queryParams.createTimeEnd = "";
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      }
+    },
+
+    //激活时间
+    activationTime(e) {
+      if (e) {
+        this.queryParams.activeTimeStart = e[0];
+        this.queryParams.activeTimeEnd = e[1];
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      } else {
+        this.queryParams.activeTimeStart = "";
+        this.queryParams.activeTimeEnd = "";
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      }
+    },
+
+    // 关闭弹框
+    close() {
+      this.exchangeShow = false
+      this.getList();
+    },
+  },
+};
+</script>
+<style lang="scss">
+.ticket-table {
+  thead {
+    .el-checkbox {
+      display: none !important;
+    }
+  }
+}
+</style>