#78 线上盲票指定门店后售价可为0、门店渠道角色转换、门店修改上级渠道

Merge realizado
lsx mesclou 10 commits de mangpiao/test em mangpiao/master há 1 ano atrás

+ 17 - 0
src/api/admin/channel.js

@@ -69,3 +69,20 @@ export function updateChannelStatus(data) {
 }
 
 
+//门店转换成渠道
+export function salesiteTransform(data) {
+  return request({
+    url: '/api/v1/mp/admin/salesite/transform',
+    method: 'post',
+    data: data
+  })
+}
+
+//渠道转换成门店
+export function channelTransform(data) {
+  return request({
+    url: '/api/v1/mp/admin/channel/transform',
+    method: 'post',
+    data: data
+  })
+}

+ 48 - 0
src/router/index.js

@@ -314,6 +314,42 @@ export const constantRoutes = [
         component: (resolve) => require(['@/views/business/marketing/detail'], resolve),
         name: 'MarketingQuery',
         meta: { title: '抽奖活动详情' , activeMenu: '/marketing/marketing', noCache: true }
+      },
+      {
+        path: 'groupLottery',
+        component: (resolve) => require(['@/views/business/groupLottery'], resolve),
+        name: 'LotteryList',
+        meta: { title: '拼团活动设置' , activeMenu: '/marketing/groupLottery' }
+      },
+      {
+        path: 'LotteryAdd',
+        component: (resolve) => require(['@/views/business/groupLottery/add'], resolve),
+        name: 'LotteryAdd',
+        meta: { title: '创建拼团活动' , activeMenu: '/marketing/groupLottery' }
+      },
+      {
+        path: 'LotteryDetails',
+        component: (resolve) => require(['@/views/business/groupLottery/detailList'], resolve),
+        name: 'LotteryDetails',
+        meta: { title: '拼团详情列表' , activeMenu: '/marketing/groupLottery' }
+      },
+      {
+        path: 'groupLotteryMsg',
+        component: (resolve) => require(['@/views/business/groupLottery/detailListMsg'], resolve),
+        name: 'groupLotteryMsg',
+        meta: { title: '拼团详情信息' , activeMenu: '/marketing/groupLottery' }
+      },
+      {
+        path: 'lottery/edit',
+        component: (resolve) => require(['@/views/business/groupLottery/add'], resolve),
+        name: 'LotteryEdit',
+        meta: { title: '修改拼团活动' , activeMenu: '/marketing/groupLottery', noCache: true }
+      },
+      {
+        path: 'lottery/query',
+        component: (resolve) => require(['@/views/business/groupLottery/detail'], resolve),
+        name: 'Lottery/Query',
+        meta: { title: '拼团活动详情' , activeMenu: '/marketing/groupLottery', noCache: true }
       }
     ]
   },
@@ -328,6 +364,18 @@ export const constantRoutes = [
         name: 'ChannelDetail',
         meta: { title: '经销商订单查看' , activeMenu: '/order/channel', noCache: true }
       },
+      {
+        path: 'groupLotteryOrder',
+        component: (resolve) => require(['@/views/order/groupLotteryOrder'], resolve),
+        name: 'groupLotteryOrder',
+        meta: { title: '拼团抽奖订单' , activeMenu: '/order/groupLotteryOrder', noCache: true }
+      },
+      {
+        path: 'groupLotteryOrder/query',
+        component: (resolve) => require(['@/views/order/groupLotteryOrder/detail'], resolve),
+        name: 'groupLotteryOrderDetail',
+        meta: { title: '拼团抽奖订单查看' , activeMenu: '/order/groupLotteryOrder', noCache: true }
+      },
       {
         path: 'deliver/query',
         component: (resolve) => require(['@/views/order/deliver/detail'], resolve),

+ 14 - 3
src/views/business/channel/childs.vue

@@ -154,7 +154,7 @@
                  <span v-if="getValue(scope.row.status) == 1" > 停用</span>
                  <span v-if="getValue(scope.row.status) == 2" > 启用</span>
                </el-button>
-
+               <el-button size="mini" type="text" v-if="scope.row.isTransform" @click="changeUpdate(scope.row)" v-hasPermi="['business:channel:edit']">转换角色</el-button>
              <!-- <el-button
                 size="mini"
                 type="text"
@@ -192,7 +192,8 @@
       :edit-id="editId"
       @close="hideDialog"
     />
-
+    <!-- 渠道转换门店 -->
+    <change-store v-if="changeShow" :dialog-visible="changeShow" @saveSuccess="submitSuccess" :edit-id="editId" @close="hideDialog" />
   </div>
 </template>
 
@@ -202,11 +203,13 @@ import { listChannel, updateChannelStatus} from "@/api/admin/channel";
 import { listAreaByPid} from "@/api/admin/area";
 import ChannelCreate from './components/Create'
 import ChannelDetail from './components/Detail'
+import ChangeStore from './components/ChangeStore.vue'
 export default {
   name: "ChannelIndex",
   components: {
     ChannelCreate,
-    ChannelDetail
+    ChannelDetail,
+    ChangeStore
   },
   data() {
     return {
@@ -220,6 +223,7 @@ export default {
       createShow: false,
       // 详情
       detailShow: false,
+      changeShow: false,
       provinceList:[],
       cityList:[],
       areaList:[],
@@ -307,6 +311,12 @@ export default {
       }
     },
 
+    // 转换身份
+    changeUpdate(row) {
+      this.changeShow = true
+      this.editId = row.channelId
+    },
+
     // 省
    /* getProvinceList(){
       this.cityList = []
@@ -400,6 +410,7 @@ export default {
     hideDialog(){
       this.createShow = false
       this.detailShow = false
+      this.changeShow = false
     },
 
     getDesc(val) {

+ 183 - 0
src/views/business/channel/components/ChangeStore.vue

@@ -0,0 +1,183 @@
+<template>
+  <el-dialog title="渠道转换门店" :visible.sync="dialogVisible" width="750px" :append-to-body="true" :before-close="close" :destroy-on-close="true" :close-on-click-modal="false">
+    <el-form ref="form" :model="form" :rules="rules" style="max-height: 375px;overflow: auto;margin-top: 30px;">
+      <el-form-item label="上级渠道" prop="parentId">
+        <el-select v-model="form.parentId" placeholder="请选择上级渠道" style="width: 60%;" filterable clearable :filter-method="dataFilter">
+          <el-option v-for="(item) in channelList" :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>
+    <div style="width: 100%;text-align: center;">谨慎操作,点击确定后转换,转换完成请到门店列表查看</div>
+    <div slot="footer" class="dialog-footer">
+      <el-button @click="close">取 消</el-button>
+      <el-button type="primary" :disabled="loading" @click="saveClick">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<script>
+import { listAllChannel, channelTransform } from "@/api/admin/channel";
+export default {
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false
+    },
+    editId: [Number, String] //  编辑用
+  },
+
+  data() {
+    return {
+      loading: false,
+      // 上级渠道列表
+      channelList: [],
+      channelCopyList: [],
+      // 表单参数
+      form: {
+        parentId: null,
+      },
+      // 表单校验
+      rules: {
+        parentId: [
+          { required: true, message: "请选择门店所属上级渠道", trigger: "change" }
+        ],
+      },
+    };
+  },
+  mounted() {
+    this.getChannelList()
+  },
+  methods: {
+    // 获取上级渠道下拉列表
+    getChannelList() {
+      listAllChannel().then(response => {
+        this.channelList = response.data || [];
+        this.channelCopyList = response.data || [];
+      });
+    },
+    dataFilter(val) {
+      if (val) { //val存在
+        this.channelList = this.channelCopyList.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.channelList = this.channelCopyList;
+      }
+    },
+    saveClick() {
+      this.loading = true
+      const subForm = this.$refs["form"]
+      subForm.validate(valid => {
+        if (valid) {
+          this.submitForm(this.form);
+        } else {
+          this.loading = false;
+          // 提示第一个error
+          this.getFormErrorMessage(subForm);
+          return false;
+        }
+      });
+    },
+
+    /**
+     * 保存
+     */
+    submitForm(params) {
+      if (this.editId) {
+        params.channelId = this.editId;
+      }
+      channelTransform(params).then(response => {
+        this.loading = false
+        this.$message.success('转换门店成功')
+        this.$emit('saveSuccess')
+        this.close()
+      }).catch(() => {
+        this.loading = false
+      });
+    },
+
+    /**
+     * 关闭窗口
+     */
+    close() {
+      this.$emit("close");
+      this.form = {};
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+.tag {
+  margin-right: 15px;
+  width: 90px;
+  text-align: center;
+  cursor: pointer;
+}
+
+.tag-select {
+  background-color: #409eff !important;
+  border-color: #409eff !important;
+  color: #fff !important;
+}
+
+.cover-content-item {
+  width: 220px;
+  float: left;
+  position: relative;
+  .cover-img {
+    width: 200px;
+    height: 100px;
+  }
+  .cover-mark {
+    position: absolute;
+    top: 0px;
+    right: 28px;
+    z-index: 1;
+    color: red;
+    cursor: pointer;
+    visibility: hidden;
+  }
+  .select {
+    visibility: visible !important;
+  }
+}
+
+.dialog-footer {
+  text-align: center;
+}
+</style>
+
+<style lang="scss">
+.ygp-form-items {
+  .el-form-item {
+    padding: 0 5px;
+  }
+  .el-form-item__label {
+    line-height: 1.2;
+    padding-bottom: 8px;
+    word-break: break-all;
+    word-wrap: break-word;
+    color: #333;
+  }
+
+  .el-form-item__error {
+    position: relative;
+    top: auto;
+    left: auto;
+  }
+
+  .el-form-item.is-desc_text {
+    .el-form-item__label {
+      display: none;
+    }
+  }
+}
+</style>

+ 124 - 206
src/views/business/channel/index.vue

@@ -20,23 +20,10 @@
       <el-col :span="24" :xs="24">
         <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
           <el-form-item label="渠道名称" prop="name">
-            <el-input
-              v-model="queryParams.name"
-              placeholder="请输入渠道名称"
-              clearable
-              size="small"
-              style="width: 240px"
-              @keyup.enter.native="handleQuery"
-            />
+            <el-input v-model="queryParams.name" placeholder="请输入渠道名称" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
           </el-form-item>
           <el-form-item label="渠道级别" prop="level">
-            <el-select
-              v-model="queryParams.level"
-              placeholder="选择渠道级别"
-              clearable
-              size="small"
-              @change="handleQuery()"
-              style="width: 200px;margin-right: 1px;">
+            <el-select v-model="queryParams.level" placeholder="选择渠道级别" clearable size="small" @change="handleQuery()" style="width: 200px;margin-right: 1px;">
               <el-option label="全部" value="" />
               <el-option label="1级渠道" value="1" />
               <el-option label="2级渠道" value="2" />
@@ -47,53 +34,19 @@
             </el-select>
           </el-form-item>
           <el-form-item label="手机号码" prop="mobile">
-            <el-input
-              v-model="queryParams.mobile"
-              placeholder="请输入手机号码"
-              clearable
-              size="small"
-              style="width: 240px"
-              @keyup.enter.native="handleQuery"
-            />
+            <el-input v-model="queryParams.mobile" placeholder="请输入手机号码" clearable size="small" style="width: 240px" @keyup.enter.native="handleQuery" />
+          </el-form-item>
+          <el-form-item label="地区">
+            <el-select v-model="queryParams.provinceId" placeholder="选择省份" clearable size="small" @change="getCityList()" style="width: 120px;margin-right: 1px;">
+              <el-option v-for="item in provinceList" :key="item.areaId" :label="item.areaName" :value="item.areaId" />
+            </el-select>
+            <el-select v-model="queryParams.cityId" placeholder="选择市" clearable size="small" @change="getAreaList()" style="width: 120px;margin-right: 1px;">
+              <el-option v-for="item in cityList" :key="item.areaId" :label="item.areaName" :value="item.areaId" />
+            </el-select>
+            <el-select v-model="queryParams.areaId" placeholder="选择区" clearable size="small" style="width: 120px;margin-right: 1px;">
+              <el-option v-for="item in areaList" :key="item.areaId" :label="item.areaName" :value="item.areaId" />
+            </el-select>
           </el-form-item>
-         <el-form-item label="地区">
-           <el-select
-             v-model="queryParams.provinceId"
-             placeholder="选择省份"
-             clearable
-             size="small"
-             @change="getCityList()"
-             style="width: 120px;margin-right: 1px;">
-             <el-option
-               v-for="item in provinceList"
-               :key="item.areaId"
-               :label="item.areaName"
-               :value="item.areaId"
-             />
-           </el-select>
-           <el-select
-             v-model="queryParams.cityId"
-             placeholder="选择市"
-             clearable
-             size="small"
-              @change="getAreaList()"
-             style="width: 120px;margin-right: 1px;">
-             <el-option
-               v-for="item in cityList"
-               :key="item.areaId"
-               :label="item.areaName"
-               :value="item.areaId"
-             />
-           </el-select>
-           <el-select v-model="queryParams.areaId" placeholder="选择区" clearable size="small" style="width: 120px;margin-right: 1px;">
-             <el-option
-               v-for="item in areaList"
-               :key="item.areaId"
-               :label="item.areaName"
-               :value="item.areaId"
-             />
-           </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="resetQuery">重置</el-button>
@@ -102,34 +55,25 @@
 
         <el-row :gutter="10" class="mb8">
           <el-col :span="1.5">
-            <el-button
-              type="primary"
-              icon="el-icon-plus"
-              size="mini"
-              @click="handleAdd"
-              v-hasPermi="['business:channel:add']"
-            >添加一级渠道</el-button>
+            <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['business:channel:add']">添加一级渠道</el-button>
           </el-col>
           <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
 
-        <el-table v-loading="loading" :data="channelList" @sort-change="sortChannelId" >
+        <el-table v-loading="loading" :data="channelList" @sort-change="sortChannelId">
           <el-table-column label="渠道编号" sortable="custom" prop="channelId" width="100px" />
-          <el-table-column label="渠道名称" prop="name" show-overflow-tooltip  width="180px">
+          <el-table-column label="渠道名称" prop="name" show-overflow-tooltip width="180px">
             <template slot-scope="scope">
 
-              <el-button
-                  v-if="scope.row.childCnt > 0"
-                  size="mini"
-                  type="text"
-                  @click="handleView(scope.row)"
-                >
-                  <pre>{{scope.row.name}}</pre>
+              <el-button v-if="scope.row.childCnt > 0" size="mini" type="text" @click="handleView(scope.row)">
+                <pre>{{scope.row.name}}</pre>
               </el-button>
-              <span v-else><pre>{{scope.row.name}}</pre></span>
+              <span v-else>
+                <pre>{{scope.row.name}}</pre>
+              </span>
             </template>
           </el-table-column>
-          <el-table-column label="手机号码" prop="mobile" show-overflow-tooltip  width="120px"/>
+          <el-table-column label="手机号码" prop="mobile" show-overflow-tooltip width="120px" />
           <el-table-column label="佣金比例" prop="commRate" sortable="custom">
             <template slot-scope="scope">
               {{scope.row.commRate}}%
@@ -140,47 +84,28 @@
               {{scope.row.level}}级渠道
             </template>
           </el-table-column>
-          <el-table-column label="门店数" sortable="custom" prop="siteCnt"  />
-          <el-table-column label="用户数" sortable="custom" prop="userCnt"  />
+          <el-table-column label="门店数" sortable="custom" prop="siteCnt" />
+          <el-table-column label="用户数" sortable="custom" prop="userCnt" />
           <el-table-column label="注册时间" prop="createdTime" min-width="150px">
             <template slot-scope="{ row }">
               {{ parseTime(row.createdTime) }}
             </template>
           </el-table-column>
           <el-table-column label="状态" key="statusV">
-           <template slot-scope="{ row }">
-             <el-tag :type="JSON.parse(row.status).value == '1' ? 'success' : 'info'">{{ JSON.parse(row.status).desc }}</el-tag>
-           </template>
+            <template slot-scope="{ row }">
+              <el-tag :type="JSON.parse(row.status).value == '1' ? 'success' : 'info'">{{ JSON.parse(row.status).desc }}</el-tag>
+            </template>
           </el-table-column>
-          <el-table-column
-            label="操作"
-            align="center"
-            width="200"
-            class-name="small-padding fixed-width"
-          >
+          <el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
             <template slot-scope="scope" v-if="scope.row.userId !== 1">
-              <el-button
-                size="mini"
-                type="text"
-                @click="handleDetail(scope.row)"
-                v-hasPermi="['business:channel:query']"
-              >查看</el-button>
-              <el-button
-                size="mini"
-                type="text"
-                @click="handleUpdate(scope.row)"
-                v-hasPermi="['business:channel:edit']"
-              >编辑</el-button>
-              <el-button
-                  size="mini"
-                  type="text"
-                  @click="handleStatusChange(scope.row)"
-                  v-hasPermi="['business:channel:edit']"
-                >
-                  <span v-if="getValue(scope.row.status) == 1" > 停用</span>
-                  <span v-if="getValue(scope.row.status) == 2" > 启用</span>
-                </el-button>
-             <!-- <el-switch
+              <el-button size="mini" type="text" @click="handleDetail(scope.row)" v-hasPermi="['business:channel:query']">查看</el-button>
+              <el-button size="mini" type="text" @click="handleUpdate(scope.row)" v-hasPermi="['business:channel:edit']">编辑</el-button>
+              <el-button size="mini" type="text" @click="handleStatusChange(scope.row)" v-hasPermi="['business:channel:edit']">
+                <span v-if="getValue(scope.row.status) == 1"> 停用</span>
+                <span v-if="getValue(scope.row.status) == 2"> 启用</span>
+              </el-button>
+              <el-button size="mini" type="text" v-if="scope.row.isTransform" @click="changeUpdate(scope.row)" v-hasPermi="['business:channel:edit']">转换角色</el-button>
+              <!-- <el-switch
                style="margin-left: 9px;"
                v-model="scope.row.statusV"
                active-value="1"
@@ -189,7 +114,7 @@
                @change="handleStatusChange(scope.row)"
              ></el-switch> -->
 
-             <!-- <el-button
+              <!-- <el-button
                 size="mini"
                 type="text"
                 disabled
@@ -201,49 +126,34 @@
           </el-table-column>
         </el-table>
 
-        <pagination
-          v-show="total>0"
-          :total="total"
-          :page.sync="pageParams.pageNum"
-          :limit.sync="pageParams.pageSize"
-          @pagination="getList"
-        />
+        <pagination v-show="total>0" :total="total" :page.sync="pageParams.pageNum" :limit.sync="pageParams.pageSize" @pagination="getList" />
       </el-col>
     </el-row>
     <!-- 新建 -->
-    <channel-create
-      v-if="createShow"
-      :dialog-visible="createShow"
-      :edit-id="editId"
-      @saveSuccess="submitSuccess"
-      @close="hideDialog"
-    />
-
+    <channel-create v-if="createShow" :dialog-visible="createShow" :edit-id="editId" @saveSuccess="submitSuccess" @close="hideDialog" />
     <!-- 详情 -->
-    <channel-detail
-      v-if="detailShow"
-      :dialog-visible="detailShow"
-      :edit-id="editId"
-      @close="hideDialog"
-    />
-
+    <channel-detail v-if="detailShow" :dialog-visible="detailShow" :edit-id="editId" @close="hideDialog" />
+    <!-- 渠道转换门店 -->
+    <change-store v-if="changeShow" :dialog-visible="changeShow" :edit-id="editId" @close="hideDialog" @saveSuccess="submitSuccess" />
   </div>
 </template>
 
 <script>
 import { getToken } from "@/utils/auth";
-import { treeChannel, listChannel, updateChannelStatus} from "@/api/admin/channel";
-import { listAreaByPid} from "@/api/admin/area";
+import { treeChannel, listChannel, updateChannelStatus } from "@/api/admin/channel";
+import { listAreaByPid } from "@/api/admin/area";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import ChannelCreate from './components/Create'
 import ChannelDetail from './components/Detail'
+import ChangeStore from './components/ChangeStore.vue'
 export default {
   name: "Channel",
   components: {
     Treeselect,
     ChannelCreate,
-    ChannelDetail
+    ChannelDetail,
+    ChangeStore
   },
   data() {
     return {
@@ -255,11 +165,12 @@ export default {
       ids: [],
       // 创建编辑
       createShow: false,
+      changeShow: false,
       // 详情
       detailShow: false,
-      provinceList:[],
-      cityList:[],
-      areaList:[],
+      provinceList: [],
+      cityList: [],
+      areaList: [],
       // 编辑项ID
       editId: null,
       // 显示搜索条件
@@ -269,7 +180,7 @@ export default {
       // 用户表格数据
       channelList: [],
       channelOptions: [],
-      channelName:"",
+      channelName: "",
       // 状态数据字典
       statusOptions: [],
       // 表单参数
@@ -282,44 +193,43 @@ export default {
       queryParams: {
         name: "",
         mobile: "",
-        provinceId:"",
-        cityId:"",
-        areaId:""
+        provinceId: "",
+        cityId: "",
+        areaId: ""
       },
       pageParams: {
         pageNum: 1,
         pageSize: 10,
         orderByColumn: 'channelId',
         isAsc: 'desc',
-
-      }
+      },
     };
   },
   watch: {
     // 根据渠道名称筛选渠道树
     //channelName(val) {
-      // this.$refs.tree.filter(val);
+    // this.$refs.tree.filter(val);
     //}
   },
   mounted() {
-     this.getProvinceList()
+    this.getProvinceList()
 
   },
   created() {
-     this.getList();
+    this.getList();
   },
   methods: {
     /** 查询用户列表 */
     getList() {
       this.loading = true;
-      listChannel('pageNum='+this.pageParams.pageNum + '&pageSize='+this.pageParams.pageSize+'&orderByColumn='+ this.pageParams.orderByColumn +'&isAsc='+ this.pageParams.isAsc +'&', this.queryParams).then(response => {
-          this.channelList = response.rows;
-          this.channelList.forEach(item => {
-              item.statusV = JSON.parse(item.status).value+""
-          })
-          this.total = response.total;
-          this.loading = false;
-        }
+      listChannel('pageNum=' + this.pageParams.pageNum + '&pageSize=' + this.pageParams.pageSize + '&orderByColumn=' + this.pageParams.orderByColumn + '&isAsc=' + this.pageParams.isAsc + '&', this.queryParams).then(response => {
+        this.channelList = response.rows;
+        this.channelList.forEach(item => {
+          item.statusV = JSON.parse(item.status).value + ""
+        })
+        this.total = response.total;
+        this.loading = false;
+      }
       );
     },
     // 节点单击事件
@@ -329,50 +239,50 @@ export default {
     },
     // 懒加载节点
     loadNode(node, resolve) {
-      if(node.level === 0){
-       treeChannel({}).then(response => {
+      if (node.level === 0) {
+        treeChannel({}).then(response => {
           return resolve(response.data);
-       });
-      }else{
+        });
+      } else {
         var params = {
-          parentId:node.data.channelId
+          parentId: node.data.channelId
         }
         treeChannel(params).then(response => {
-           return resolve(response.data);
+          return resolve(response.data);
         });
       }
     },
 
     //切换排序
-    sortChannelId(row){
-      if (row){
-        let prop =  row.prop == 'commRate' ? ('t1.'+ row.prop) : row.prop;
+    sortChannelId(row) {
+      if (row) {
+        let prop = row.prop == 'commRate' ? ('t1.' + row.prop) : row.prop;
         this.pageParams.orderByColumn = prop
-        this.pageParams.isAsc = row.order=='ascending'?"asc":"desc";
+        this.pageParams.isAsc = row.order == 'ascending' ? "asc" : "desc";
         this.getList()
       }
 
     },
 
-    refreshChannelTree(){
+    refreshChannelTree() {
       treeChannel({}).then(response => {
-         this.channelOptions = response.data
+        this.channelOptions = response.data
       });
     },
 
     // 省
-    getProvinceList(){
+    getProvinceList() {
       this.cityList = []
       this.areaList = []
       this.queryParams.cityId = ""
       this.queryParams.areaId = ""
       listAreaByPid(0).then(response => {
         // console.log("getProvinceList"+JSON.stringify(response))
-         this.provinceList = response || [];
+        this.provinceList = response || [];
       });
     },
 
-    getCityList(){
+    getCityList() {
       this.cityList = []
       this.areaList = []
       this.queryParams.cityId = ""
@@ -380,38 +290,38 @@ export default {
       var provinceId = this.queryParams.provinceId
       listAreaByPid(provinceId).then(response => {
         // console.log("getCityList"+JSON.stringify(response))
-         this.cityList = response || [];
+        this.cityList = response || [];
       });
     },
 
-    getAreaList(){
+    getAreaList() {
       var cityId = this.queryParams.cityId
       listAreaByPid(cityId).then(response => {
         // console.log("getAreaList"+JSON.stringify(response))
-         this.areaList = response || [];
+        this.areaList = response || [];
       });
     },
 
     // 状态修改
     handleStatusChange(row) {
-      var newStatus = this.getValue(row.status) == 2?1:2
+      var newStatus = this.getValue(row.status) == 2 ? 1 : 2
       let text = this.getValue(row.status) == 2 ? "启用" : "停用";
       this.$confirm('确认要"' + text + '""' + row.name + '"渠道吗?', "警告", {
-          confirmButtonText: "确定",
-          cancelButtonText: "取消",
-          type: "warning"
-        }).then(function() {
-          var params={
-            channelId:row.channelId,
-            status: newStatus
-          }
-          return updateChannelStatus(params);
-        }).then(() => {
-          this.msgSuccess(text + "成功");
-          this.getList();
-        }).catch(function() {
-          // row.status = row.status === "0" ? "1" : "0";
-        });
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        var params = {
+          channelId: row.channelId,
+          status: newStatus
+        }
+        return updateChannelStatus(params);
+      }).then(() => {
+        this.msgSuccess(text + "成功");
+        this.getList();
+      }).catch(function () {
+        // row.status = row.status === "0" ? "1" : "0";
+      });
     },
 
     /** 搜索按钮操作 */
@@ -421,17 +331,17 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
-      this.queryParams= {
-         name: "",
-         mobile: "",
-         provinceId:"",
-         cityId:"",
-         areaId:""
+      this.queryParams = {
+        name: "",
+        mobile: "",
+        provinceId: "",
+        cityId: "",
+        areaId: ""
       },
-      this.resetForm("queryForm");
+        this.resetForm("queryForm");
       this.handleQuery();
     },
-    handleDetail(row){
+    handleDetail(row) {
       this.detailShow = true
       this.editId = row.channelId
     },
@@ -446,14 +356,23 @@ export default {
       this.editId = row.channelId
     },
     // 保存后的操作
-    submitSuccess(){
+    submitSuccess() {
       this.getList();
       this.refreshChannelTree();
     },
+
+    // 转换身份
+    changeUpdate(row) {
+      this.changeShow = true
+      this.editId = row.channelId
+    },
+    
+
     /**关闭弹窗*/
-    hideDialog(){
+    hideDialog() {
       this.createShow = false
       this.detailShow = false
+      this.changeShow = false
     },
 
     getDesc(val) {
@@ -476,13 +395,13 @@ export default {
       const path = "/channel/channel/childs"
       // const routerName = "BillItems"
       this.$router.push({
-        path: path ,
+        path: path,
         query: {
           parentId: parentId,
           title: title
         },
-        meta:{
-          title:"777777777777777777"
+        meta: {
+          title: "777777777777777777"
         }
       });
     },
@@ -490,5 +409,4 @@ export default {
 };
 </script>
 <style lang="sass" scoped>
-
 </style>

+ 416 - 0
src/views/business/groupLottery/add.vue

@@ -0,0 +1,416 @@
+<template>
+  <div class="app-container goods-add add-groupLottery">
+    <el-divider content-position="left">基础信息</el-divider>
+    <el-form ref="addItem" :rules="rules" :model="addData" label-width="150px">
+      <el-row :gutter="10">
+        <el-col :xs="{span: 22, offset: 0}" :sm=" {span: 18, offset: 0}" :lg="{span: 10, offset: 0}">
+          <el-form-item label="拼团活动名称:" prop="title">
+            <el-input v-model="addData.title" placeholder="输入活动名称"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="23">
+          <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" :picker-options="setYearDisabled" type="datetimerange"
+                            range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"  :default-time="['20:00:00', '20:00:00']"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="成团人数:" prop="fakeNum">
+            <el-input v-model="addData.fakeNum" type="number"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="发起拼团最大次数:" prop="fakeNum">
+            <el-input v-model="addData.fakeNum" type="number"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+        <el-form-item label="加入拼团最大次数:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" type="number"/>
+        </el-form-item>
+          </el-col>
+        <el-col :span="24">
+        <el-form-item label="参与拼团最大次数:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" type="number"/>
+        </el-form-item>
+          </el-col>
+        <el-col :span="24">
+        <el-form-item label="佣金系数:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" type="number"/>%
+        </el-form-item>
+          </el-col>
+        <el-col :span="24">
+        <el-form-item label="参与门店:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" type="text"/>
+        </el-form-item>
+          </el-col>
+        <el-col :span="24">
+          <el-form-item label="是否允许退款:" prop="type" label-width="140px">
+              <el-radio-group v-model="addData.codeType" >
+                <el-radio :label="1">是</el-radio>
+                <el-radio :label="2">否</el-radio>
+              </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-divider content-position="left">奖品设置</el-divider>
+      <el-row :gutter="10">
+        <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>
+
+    <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 { publicFileGetUrl } from "@/api/common";
+import {getMarketingDetail, 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: 'MarketingAdd',
+  components: {
+    Upload,
+    WangEditor,
+    AwardsList,
+    GoodsAdd,
+    CouponAdd,
+    CouponPkgAdd,
+    CoinAdd,
+  },
+  data() {
+    return {
+      //禁止选择当前今天之前的日期
+      setYearDisabled: {
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 8.64e7
+        }
+      },
+      id: this.$route.query.id,
+      addData: {
+        picUrl: '',//活动主图
+        startTime: '',//开始时间
+        endTime: '',//结束时间
+        fakeNum: 0,//初始用户数
+        description: '',//活动详情
+        awardsList: [],//奖级列表
+        codeType: 2,//获取类型
+      },
+      rules: {
+        title: [{required: true, message: '请输入活动名称', trigger: 'blur'}],
+        picUrl: [{required: true, message: '请上传活动封面', trigger: 'change'}],
+        dateValue: [{required: true, message: '请设置活动日期', trigger: 'change'}],
+        fakeNum:[{ pattern: /^([0-9]\d*)$/, message: "请输入正确的数字", trigger: ["blur", "change"]}]
+      },
+      // 奖级列表
+      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,//内定数量
+        }
+      ],
+      goodsTableVisible: false, // 添加商品弹框
+      couponTitle: "", // 券名称
+      couponTableVisible: false, // 添加卡券弹框
+      couponPkgTableVisible: false, // 添加券包弹框
+      coinTableVisible: false, // 添加盲豆弹框
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      dateValue: [],//开始与结束日期
+    }
+  },
+  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) {
+      getMarketingDetail(this.id).then(res => {
+        const { startTime, endTime, description, fakeNum, codeType, picUrl, realNum, title, awardsList, id } = res.data
+        this.addData = { title, dateValue:[startTime,endTime], picUrl, fakeNum, codeType, realNum, description, awardsList, id }
+        if(description) {
+          this.$refs.editor.setContent(description)
+        }
+        if(awardsList){
+          awardsList.forEach((item) => {
+              item.prizeList.forEach((ele) => {
+                (ele.picUrl = publicFileGetUrl + ele.picUrl.split(',')[0]),
+                  (ele.prizeType = JSON.parse(ele.prizeType).value);
+                  ele.couponDetail = ele.couponDetail ? encodeURI(ele.couponDetail) : ''
+              });
+          });
+          this.$nextTick(() => {
+            this.$refs.awards.add(3, awardsList)
+          })
+          this.awardsList = awardsList
+        }
+      })
+    }
+  },
+
+  methods: {
+    // 保存
+    update() {
+      this.$refs.addItem.validate((valid, items) => {
+        if (valid) {
+          if(this.addData.dateValue[0] == this.addData.dateValue[1]){
+            this.msgError('活动开始时间与结束时间不能相等!')
+            return;
+          }
+          if(this.awardsList.length < 1) {
+            this.msgError('请至少设置一个奖级的的奖品!')
+            return;
+          }
+          // 判断没有设置奖品的奖级
+          let prizeIndex = this.awardsList.findIndex((item) => {
+            return !item.prizeList.length;
+          });
+          if (prizeIndex != -1) {
+            this.$message.error(
+              `请至少设置一个奖级的的奖品!`
+            );
+            return;
+          }
+          // 判断没有设置奖级数量
+          let prizeIndexThree = this.awardsList.findIndex((item) => {
+            return !item.quantity && item.quantity != 0;
+          });
+          if (prizeIndexThree != -1) {
+            this.$message.error(
+              `请设置${this.awardsList[prizeIndexThree].name}的奖级数量!`
+            );
+            return;
+          }
+          // 判断没有设置内定数量
+          let prizeIndexTwo = this.awardsList.findIndex((item) => {
+            return !item.insideNum && item.insideNum != 0;
+          });
+          if (prizeIndexTwo != -1) {
+            this.$message.error(
+              `请设置${this.awardsList[prizeIndexTwo].name}的内定数量!`
+            );
+            return;
+          }
+
+          // 判断内定名额大于奖品名额
+          let quantityIndex = this.awardsList.findIndex((item) => {
+            return item.insideNum > item.quantity;
+          });
+          if (quantityIndex != -1) {
+            this.$message.error(
+              `${this.awardsList[quantityIndex].name}的内定名额大于奖品名额,请重新设置!`
+            );
+            return;
+          }
+          let quantityIndexTwo = this.awardsList.findIndex((item) => {
+            return item.prizeList.length != 0 && item.quantity == 0;
+          });
+          if (quantityIndexTwo != -1) {
+            this.$message.error(
+              `${this.awardsList[quantityIndexTwo].name}的名额不能为0,请重新设置!`
+            );
+            return;
+          }
+
+          this.awardsList.forEach((item) => {
+            item.prizeList = item.prizeList.map((ele) => {
+              return {
+                ...ele,
+                refId: ele.refId || ele.goodsId || ele.couponId || ele.id ,
+                prizeType: ele.prizeType,
+                quantity: ele.quantity,
+                value: Number(ele.value),
+              };
+            });
+          });
+
+          const { fakeNum, description, title, picUrl, codeType } = this.addData
+          addMarketing({
+            title,
+            description: encodeURI(description),
+            fakeNum,
+            startTime: this.addData.dateValue[0],
+            endTime: this.addData.dateValue[1],
+            awardsList: this.awardsList,
+            codeType:Number(codeType),
+            picUrl, 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'
+            })
+          }
+        }
+      })
+    },
+
+    // 添加奖品种类
+    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;
+    }
+  }
+}
+.add-groupLottery .el-input{
+  width: 340px;
+}
+</style>

+ 126 - 0
src/views/business/groupLottery/components/ActivityTable.vue

@@ -0,0 +1,126 @@
+<template>
+  <div>
+    <el-dialog
+      :title="marketingData.title"
+      width="1000px"
+      :visible.sync="dialogVisible"
+      :before-close="close"
+    >
+      <div class="dialog-search">
+        <div>参与用户数量:{{marketingData.realNum}}</div>
+        <div class="ge"></div>
+        <div>新用户数(助力用户数):{{marketingData.newUserCount}}</div>
+        <div class="ge"></div>
+        <div>抽奖码数量:{{marketingData.codeCount}}</div>
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="marketingList"
+        class="el-table"
+      >
+        <el-table-column label="用户编号" prop="userId" min-width="80" />
+        <el-table-column label="用户昵称" prop="nickName" min-width="80" />
+        <el-table-column label="抽奖码" prop="code" min-width="80" />
+        <el-table-column label="抽奖码获取时间" prop="createdTime" min-width="85">
+          <template slot-scope="scope">
+            <div>{{ parseTime(scope.row.createdTime) }}</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="奖级" prop="awardsName" min-width="50" >
+          <template slot-scope="scope">
+            <div v-if="scope.row.prizeName != ''">{{ scope.row.awardsName }}</div>
+            <div v-else> -- </div>
+          </template>
+        </el-table-column>
+        <el-table-column label="奖品名称" prop="prizeName" min-width="85" >
+          <template slot-scope="scope">
+            <div v-if="scope.row.prizeType == 'COIN'">盲豆 x{{scope.row.value}}</div>
+            <div v-else-if="scope.row.prizeName != ''">{{ scope.row.prizeName }}</div>
+            <div v-else> -- </div>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="marketingTotal > 0"
+        :total="marketingTotal"
+        :page.sync="pageParams.pageNum"
+        :limit.sync="pageParams.pageSize"
+        @pagination="getMarketingData"
+      />
+      <div class="dialog-btn">
+        <el-button size="small" @click="close"> 关 闭 </el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import { getMarketingData, getMarketingDataCodeList } from '@/api/business/marketing'
+export default {
+  name: "CouponAdd",
+  props: {
+    dialogVisible: {
+      type: Boolean,
+      default: false,
+    },
+    ids: {
+      type: Object,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      marketingList: [], // 列表
+      marketingTotal: 0, // 总数
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      marketingData: {},//
+    };
+  },
+  created() {
+    this.getMarketingData();
+  },
+  methods: {
+    // 列表
+    getMarketingData() {
+      this.loading = true;
+      getMarketingDataCodeList('pageNum='+this.pageParams.pageNum + '&pageSize='+this.pageParams.pageSize+'&',this.ids.id ).then((res) => {
+        this.marketingList = res.rows
+        this.marketingTotal = res.total;
+        this.loading = false;
+      });
+      getMarketingData(this.ids.id ).then((res) => {
+        if(res.code == 0){
+          this.marketingData = res.data
+        }
+      });
+
+    },
+
+    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>

+ 216 - 0
src/views/business/groupLottery/components/AwardsList.vue

@@ -0,0 +1,216 @@
+<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" >
+              <template slot-scope="scope">
+                <div v-if="scope.row.prizeType == '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.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="操作" 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: 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/groupLottery/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",
+        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>

+ 203 - 0
src/views/business/groupLottery/components/CouponAdd.vue

@@ -0,0 +1,203 @@
+<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>
+        <div>使用场景:</div>
+        <el-select v-model="type" placeholder="请选择使用场景" clearable @keyup.enter.native="getCouponList">
+          <el-option label="全部" value=""/>
+          <el-option label="门店消费" :value="2"/>
+          <el-option label="盲票购买" :value="1"/>
+          <el-option label="采购商品核销" :value="4"/>
+        </el-select>
+        <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,
+      type: '',
+      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,type: this.type, 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() {
+      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/groupLottery/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 {
+          prizeType: "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>

+ 210 - 0
src/views/business/groupLottery/components/GoodsAdd.vue

@@ -0,0 +1,210 @@
+<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>
+      <div class="dialog-search">
+        <div>商品类型:</div>
+        <el-select v-model="queryParams.type" placeholder="请选择商品类型" clearable @change="queryParams.pageNum = 1;getGoodsList()">
+          <el-option label="全部" value=""/>
+          <el-option label="实物商品" value="1"/>
+          <el-option label="卡密商品" value="2"/>
+        </el-select>
+        <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="type" min-width="85">
+          <template slot-scope="scope">
+            <div v-if="scope.row.type == 1">实物商品</div>
+            <div v-else-if="scope.row.type == 2">卡密商品</div>
+            <div v-else-if="scope.row.type == 3">采购商品</div>
+          </template>
+        </el-table-column>
+        <el-table-column label="是否支持兑换" prop="exchangeShow" min-width="85">
+          <template slot-scope="scope">
+            <div v-if="scope.row.exchangeShow == 1">支持兑换</div>
+            <div v-else-if="scope.row.exchangeShow == 0">不支持兑换</div>
+            <div v-else-if="scope.row.exchangeShow == 2">盲票商品</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 +
+          "&",
+        { isExcludePurchaseGoods: true, type: this.queryParams.type, 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() {
+      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>

+ 195 - 0
src/views/business/groupLottery/detail.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="app-container goods-add">
+    <el-row :gutter="10">
+      <el-col :span="24">
+        <el-divider content-position="left">基础信息</el-divider>
+        <el-form ref="addItem"  :model="addData" label-width="120px">
+          <el-row :gutter="10">
+            <el-col  :xs="{span: 22, offset: 0}" :sm=" {span: 18, offset: 0}" :lg="{span: 10, offset: 0}">
+              <el-form-item label="活动名称:" prop="title">
+                <el-input v-model="addData.title" placeholder="输入活动名称" readonly />
+              </el-form-item>
+            </el-col>
+            <el-col :span="23">
+              <el-form-item label="活动封面:" >
+                <el-image
+                  style="width: 110px;"
+                  :src="addData && addData.picUrl"
+                  :preview-src-list="[addData && addData.picUrl]"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="20">
+              <el-form-item label="活动日期:" prop="dateValue">
+                <el-date-picker value-format="timestamp" v-model="addData.dateValue" type="datetimerange" readonly
+                                range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"/>
+              </el-form-item>
+            </el-col>
+            <el-col :xs="{span: 22, offset: 0}" :sm=" {span: 18, offset: 0}" :lg="{span: 10, offset: 0}">
+              <el-form-item label="初始用户数:">
+                <el-input v-model="addData.fakeNum" readonly />
+              </el-form-item>
+            </el-col>
+            <el-col :span="18">
+              <el-form-item label="是否可无条件参与:" label-width="140px">
+                <div v-if="addData.codeType == 1">是</div>
+                <div v-else>否</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-divider content-position="left">奖品设置</el-divider>
+          <el-row :gutter="10">
+            <el-col :span="22">
+
+              <el-form-item>
+                <!-- 奖级列表 -->
+                <div class="prize" v-for="(item, index) in awardsList" :key="index">
+                  <div class="prize-top">
+                    <div>奖级:{{ item.name }}</div>
+                    <div>名额:{{item.quantity}}</div>
+                    <div>内部名额:{{item.insideNum}}</div>
+                  </div>
+                  <div class="prize-table">
+                    <el-table :data="item.prizeList" class="el-table">
+                      <el-table-column label="奖品图片" align="center">
+                        <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" align="center" >
+                        <template slot-scope="scope">
+                          <div v-if="scope.row.prizeType == 'coin'">盲豆 x{{scope.row.value}}</div>
+                          <div v-else>{{scope.row.title}}</div>
+                        </template>
+                      </el-table-column>
+                      <el-table-column label="奖品类型" align="center">
+                        <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>
+                  </div>
+                </div>
+              </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">
+                <div v-html="addData.description"></div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+
+        <el-row>
+          <el-col :span="24" style="text-align: center">
+            <el-button type="info" @click="$router.replace('/marketing/marketing')">取消</el-button>
+          </el-col>
+        </el-row>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import {getMarketingDetail, addMarketing} from '@/api/business/marketing'
+import Upload from '@/components/DragImageUpload'
+import WangEditor from '@/components/WangEditor'
+
+export default {
+  name: "add",
+  components: {
+    Upload,
+    WangEditor,
+  },
+  data() {
+    return {
+      id: this.$route.query.id,
+      addData: {
+        picUrl: '',//活动主图
+        startTime: '',//开始时间
+        endTime: '',//结束时间
+        fakeNum: 0,//初始用户数
+        description: '',//活动详情
+        awardsList: [],//奖级列表
+        codeType: '',
+      },
+      labelRadio: 1,//单选框
+
+      // 奖级列表
+      awardsList: [],
+      dateValue: [],//开始与结束日期
+    }
+  },
+  computed: {
+  },
+  created() {
+    if (this.id) {
+      getMarketingDetail(this.id).then(res => {
+        const { startTime, endTime, description, fakeNum,picUrl, codeType, realNum, title, awardsList, id } = res.data
+        this.addData = { title, dateValue:[startTime,endTime], picUrl: publicFileGetUrl + picUrl, fakeNum, codeType, realNum, description, awardsList, id }
+        if(awardsList){
+          awardsList.forEach((item) => {
+            item.prizeList.forEach((ele) => {
+              (ele.picUrl = publicFileGetUrl + ele.picUrl.split(',')[0]),
+                (ele.prizeType = JSON.parse(ele.prizeType).value);
+            });
+          });
+          this.awardsList = awardsList
+        }
+      })
+    }
+  }
+}
+</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;
+    }
+  }
+}
+.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>

+ 204 - 0
src/views/business/groupLottery/detailList.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="app-container coupon-list">
+    <el-form v-show="showSearch" :model="queryParams" ref="queryForm" :inline="true" size="small">
+      <el-form-item label="活动名称">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入活动名称"
+          clearable @clear="queryParams.pageNum = 1;getList()"
+          @keyup.enter.native="queryParams.pageNum = 1;getList()"
+        />
+      </el-form-item>
+      <el-form-item label="奖品名称">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入奖品名称"
+          clearable @clear="queryParams.pageNum = 1;getList()"
+          @keyup.enter.native="queryParams.pageNum = 1;getList()"
+        />
+      </el-form-item>
+      <el-form-item label="拼团状态">
+        <el-select v-model="queryParams.status" placeholder="请选择拼团状态" clearable @change="queryParams.pageNum = 1;getList()">
+          <el-option label="全部" value="" />
+          <el-option v-for="(item,index) in marketingStatusList"  :label="item.dictLabel" :value="Number(item.dictValue)" :key="index"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="发起人">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入发起人手机号"
+          clearable @clear="queryParams.pageNum = 1;getList()"
+          @keyup.enter.native="queryParams.pageNum = 1;getList()"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" @click="queryParams.pageNum = 1;getList()">搜索</el-button>
+        <el-button icon="el-icon-refresh" @click="getList(true)">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="10">
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-download"
+          size="small"
+          @click="handleExportDraw"
+          v-hasPermi="['business:marketing:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+    <el-table v-loading="loading" :data="tableData">
+
+      <el-table-column label="活动名称" prop="title" />
+      <el-table-column label="奖品名称" prop="a" />
+      <el-table-column label="团号" prop="realNum"/>
+      <el-table-column label="拼团价格" prop="realNum"/>
+      <el-table-column label="参团人数" prop="realNum"/>
+      <el-table-column label="成团人数" prop="realNum"/>
+      <el-table-column label="拼团状态" prop="realNum"/>
+      <el-table-column label="拼团到期时间" prop="startTime" >
+        <template slot-scope="{row}">
+          {{ parseTime(row.startTime) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="发起人" prop="realNum"/>
+      <el-table-column label="创建时间" prop="realNum"/>
+
+      <el-table-column fixed="right" align="right" label="操作" width="290">
+        <template slot-scope="{row}">
+          <el-button v-hasPermi="['business:marketing:query']" type="text" @click="show">详情</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" :ids="ids" @close="activityTableVisible = false" v-if="activityTableVisible"></activity-table>
+  </div>
+</template>
+<script>
+import { getMarketingList, delMarketing, setMarketingStatus, setMarketingStatusOff, ticketMarketingExport, getMarketingCopy } from '@/api/business/marketing'
+import ActivityTable from "./components/ActivityTable";
+export default {
+  name: 'groupLottery',
+  components:{
+    ActivityTable,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      tableData: [],
+      queryParams: {},
+      total: 0,
+      ids: {},
+      activityTableVisible: false,
+      marketingStatusList: []
+    }
+  },
+  created() {
+    // this.getList(true)
+    // this.getMarketingStatus()
+  },
+  methods: {
+    getList(reset) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+      if (reset) {
+        this.queryParams = { pageNum: 1, pageSize: 10 }
+      }
+      getMarketingList('pageNum='+this.queryParams.pageNum + '&pageSize='+this.queryParams.pageSize+'&', this.queryParams).then(res => {
+        this.loading = false
+        if (res.code === 0) {
+          this.tableData = res.rows
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    getMarketingStatus(){
+      this.getDicts('marketing_status').then(res=>{
+        this.marketingStatusList = res.data
+      })
+    },
+    setStatus(item, status) {
+      this.$confirm(`确认${status === 'on' ? '开启' : '关闭'}活动 “${item.title}” 吗?`, `${status === 'on' ? '开启' : '关闭'}活动`, {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        if (status === 'on'){
+          setMarketingStatus(item.id).then(res => {
+            if (res.code === 0) {
+              this.$message.success('开启已完成!')
+              this.getList()
+            }
+          })
+        }else{
+          setMarketingStatusOff(item.id).then(res => {
+            if (res.code === 0) {
+              this.$message.success('关闭已完成!')
+              this.getList()
+            }
+          })
+        }
+      })
+    },
+    del(item) {
+      this.$confirm(`确认删除活动 “${item.title}” 吗?`, '删除活动', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        delMarketing(item.id).then(res => {
+          if (res.code === 0) {
+            this.$message.success('操作已完成!')
+            this.getList()
+          }
+        })
+      })
+    },
+    MarketingCopy(id,title) {
+      this.$confirm(`确认复制活动 “${title}” 吗?`, '复制活动', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        getMarketingCopy(id).then(res => {
+          if (res.code === 0) {
+            this.$message.success('操作已完成!')
+            this.getList()
+          }
+        })
+      })
+    },
+
+    // 导出订单
+    handleExportDraw() {
+      this.$confirm("是否确认导出活动数据?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.vloading = this.$loading({
+            lock: true,
+            text: "正在导出活动数据.....",
+            background: "rgba(0, 0, 0, 0.7)",
+          });
+          return ticketMarketingExport(this.queryParams);
+        })
+        .then((response) => {
+          this.vloading.close();
+          this.download(response.msg);
+        })
+        .catch(() => {
+          this.vloading.close();
+        });
+    },
+  }
+}
+</script>

+ 321 - 0
src/views/business/groupLottery/detailListMsg.vue

@@ -0,0 +1,321 @@
+<template>
+  <div class="app-container goods-add add-groupLottery">
+    <el-divider content-position="left">拼团信息</el-divider>
+    <el-form ref="addItem"  :model="addData" label-width="150px">
+      <el-row :gutter="10">
+        <el-col :xs="{span: 22, offset: 0}" :sm=" {span: 18, offset: 0}" :lg="{span: 10, offset: 0}">
+          <el-form-item label="拼团活动名称:" prop="title">
+            <el-input v-model="addData.title" placeholder="输入活动名称"/>
+          </el-form-item>
+        </el-col>
+
+        <el-col :span="24">
+          <el-form-item label="参团人数:" prop="fakeNum">
+            <el-input v-model="addData.fakeNum" type="number"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="成团人数:" prop="fakeNum">
+            <el-input v-model="addData.fakeNum" type="number"/>
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+        <el-form-item label="拼团金额:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" type="number"/>
+        </el-form-item>
+          </el-col>
+        <el-col :span="24">
+        <el-form-item label="拼团状态:" prop="fakeNum">
+          <el-input v-model="addData.fakeNum" />
+        </el-form-item>
+          </el-col>
+
+      </el-row>
+      <el-divider content-position="left">团员信息</el-divider>
+      <el-row :gutter="10">
+        <el-col :span="22">
+
+        </el-col>
+      </el-row>
+      <el-table
+                           :data="tableData"
+                           style="width: 100%"
+                           > 
+                           <template v-for="(item,index) in columns">
+                             <el-table-column
+                                align="left"
+                                :sortable="item.sortable"
+                                :prop="item.prop"
+                                :label="item.name"
+                                >
+                               <template slot-scope="scope" >
+                                   <span >{{scope.row[item.prop]}}</span>
+                               </template>
+                             </el-table-column>
+                           </template>
+
+                           </el-table>
+    </el-form>
+
+    <!-- <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> -->
+
+  </div>
+</template>
+
+<script>
+import { publicFileGetUrl } from "@/api/common";
+import {getMarketingDetail, 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: 'MarketingAdd',
+  components: {
+    Upload,
+    WangEditor,
+    AwardsList,
+    GoodsAdd,
+    CouponAdd,
+    CouponPkgAdd,
+    CoinAdd,
+  },
+  data() {
+    return {
+      tableData:[],
+      addData:{},
+      columns:[
+          {prop:'number',name:'编号',sortable:false,width:'64px'},
+          {prop:'accountName',name:'用户名',sortable:false,width:'64px'},
+          {prop:'code',name:'门店名称',sortable:false,width:'60px'},
+          {prop:'name',name:'参团时间',sortable:false,width:'65px'},
+          {prop:'buy',name:'拼团价格',sortable:false,width:'56px'},
+          {prop:'sell',name:'支付状态',sortable:false,width:'56px'},
+          // {prop:'trader',name:'交易员'},
+        ],
+    }
+  },
+  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) {
+      getMarketingDetail(this.id).then(res => {
+        const { startTime, endTime, description, fakeNum, codeType, picUrl, realNum, title, awardsList, id } = res.data
+        this.addData = { title, dateValue:[startTime,endTime], picUrl, fakeNum, codeType, realNum, description, awardsList, id }
+        if(description) {
+          this.$refs.editor.setContent(description)
+        }
+        if(awardsList){
+          awardsList.forEach((item) => {
+              item.prizeList.forEach((ele) => {
+                (ele.picUrl = publicFileGetUrl + ele.picUrl.split(',')[0]),
+                  (ele.prizeType = JSON.parse(ele.prizeType).value);
+                  ele.couponDetail = ele.couponDetail ? encodeURI(ele.couponDetail) : ''
+              });
+          });
+          this.$nextTick(() => {
+            this.$refs.awards.add(3, awardsList)
+          })
+          this.awardsList = awardsList
+        }
+      })
+    }
+  },
+
+  methods: {
+    // 保存
+    update() {
+      this.$refs.addItem.validate((valid, items) => {
+        if (valid) {
+          if(this.addData.dateValue[0] == this.addData.dateValue[1]){
+            this.msgError('活动开始时间与结束时间不能相等!')
+            return;
+          }
+          if(this.awardsList.length < 1) {
+            this.msgError('请至少设置一个奖级的的奖品!')
+            return;
+          }
+          // 判断没有设置奖品的奖级
+          let prizeIndex = this.awardsList.findIndex((item) => {
+            return !item.prizeList.length;
+          });
+          if (prizeIndex != -1) {
+            this.$message.error(
+              `请至少设置一个奖级的的奖品!`
+            );
+            return;
+          }
+          // 判断没有设置奖级数量
+          let prizeIndexThree = this.awardsList.findIndex((item) => {
+            return !item.quantity && item.quantity != 0;
+          });
+          if (prizeIndexThree != -1) {
+            this.$message.error(
+              `请设置${this.awardsList[prizeIndexThree].name}的奖级数量!`
+            );
+            return;
+          }
+          // 判断没有设置内定数量
+          let prizeIndexTwo = this.awardsList.findIndex((item) => {
+            return !item.insideNum && item.insideNum != 0;
+          });
+          if (prizeIndexTwo != -1) {
+            this.$message.error(
+              `请设置${this.awardsList[prizeIndexTwo].name}的内定数量!`
+            );
+            return;
+          }
+
+          // 判断内定名额大于奖品名额
+          let quantityIndex = this.awardsList.findIndex((item) => {
+            return item.insideNum > item.quantity;
+          });
+          if (quantityIndex != -1) {
+            this.$message.error(
+              `${this.awardsList[quantityIndex].name}的内定名额大于奖品名额,请重新设置!`
+            );
+            return;
+          }
+          let quantityIndexTwo = this.awardsList.findIndex((item) => {
+            return item.prizeList.length != 0 && item.quantity == 0;
+          });
+          if (quantityIndexTwo != -1) {
+            this.$message.error(
+              `${this.awardsList[quantityIndexTwo].name}的名额不能为0,请重新设置!`
+            );
+            return;
+          }
+
+          this.awardsList.forEach((item) => {
+            item.prizeList = item.prizeList.map((ele) => {
+              return {
+                ...ele,
+                refId: ele.refId || ele.goodsId || ele.couponId || ele.id ,
+                prizeType: ele.prizeType,
+                quantity: ele.quantity,
+                value: Number(ele.value),
+              };
+            });
+          });
+
+          const { fakeNum, description, title, picUrl, codeType } = this.addData
+          addMarketing({
+            title,
+            description: encodeURI(description),
+            fakeNum,
+            startTime: this.addData.dateValue[0],
+            endTime: this.addData.dateValue[1],
+            awardsList: this.awardsList,
+            codeType:Number(codeType),
+            picUrl, 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'
+            })
+          }
+        }
+      })
+    },
+
+    // 添加奖品种类
+    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;
+    }
+  }
+}
+.add-groupLottery .el-input{
+  width: 340px;
+}
+</style>

+ 204 - 0
src/views/business/groupLottery/index.vue

@@ -0,0 +1,204 @@
+<template>
+  <div class="app-container coupon-list">
+    <el-form v-show="showSearch" :model="queryParams" ref="queryForm" :inline="true" size="small">
+      <el-form-item label="活动名称">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入活动名称"
+          clearable @clear="queryParams.pageNum = 1;getList()"
+          @keyup.enter.native="queryParams.pageNum = 1;getList()"
+        />
+      </el-form-item>
+      <el-form-item label="活动状态">
+        <el-select v-model="queryParams.status" placeholder="请选择活动状态" clearable @change="queryParams.pageNum = 1;getList()">
+          <el-option label="全部" value="" />
+          <el-option v-for="(item,index) in marketingStatusList"  :label="item.dictLabel" :value="Number(item.dictValue)" :key="index"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" @click="queryParams.pageNum = 1;getList()">搜索</el-button>
+        <el-button icon="el-icon-refresh" @click="getList(true)">重置</el-button>
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="10">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="$router.push({ name: 'LotteryAdd' })"
+          v-hasPermi="['business:groupLottery:add']"
+        >创建拼团活动</el-button>
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-download"
+          size="small"
+          @click="handleExportDraw"
+          v-hasPermi="['business:marketing:export']"
+        >导出中奖数据</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+    <el-table v-loading="loading" :data="tableData">
+      <el-table-column label="活动编号" prop="id" width="80" />
+      <el-table-column label="活动名称" prop="title" />
+      <el-table-column label="参与人数" prop="realNum"/>
+      <el-table-column label="开始时间" prop="startTime" >
+        <template slot-scope="{row}">
+          {{ parseTime(row.startTime) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="结束时间" prop="endTime" >
+        <template slot-scope="{row}">
+          {{ parseTime(row.endTime) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="状态" prop="status">
+        <template slot-scope="{row}">
+          <el-tag :type="JSON.parse(row.status).value === 4 || JSON.parse(row.status).value === -1 ? 'info' : 'success'">{{ JSON.parse(row.status).desc }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column fixed="right" align="right" label="操作" width="290">
+        <template slot-scope="{row}">
+          <el-button v-hasPermi="['business:marketing:query']" type="text" @click="$router.push({ name: 'MarketingQuery', query: { id: row.id } })">查看</el-button>
+          <el-button v-hasPermi="['business:marketing:query']" type="text">上架</el-button>
+          <el-button v-if=" JSON.parse(row.status).value === 3 || JSON.parse(row.status).value === 0 || JSON.parse(row.status).value === 2 " v-hasPermi="['business:marketing:edit']" type="text" @click="$router.push({ name: 'MarketingEdit', query: { id: row.id } })">编辑</el-button>
+          <el-button v-if=" JSON.parse(row.status).value === 3 || JSON.parse(row.status).value === 4 || JSON.parse(row.status).value === -1 " v-hasPermi="['business:marketing:queryData']" type="text"  @click="activityTableVisible = true, ids = { id:row.id, title:row.title, realNum:row.realNum }">活动数据</el-button>
+          <el-button v-if=" JSON.parse(row.status).value === 0 " v-hasPermi="['business:marketing:on']" type="text" @click="setStatus(row, 'on')">开启</el-button>
+          <el-button v-if=" JSON.parse(row.status).value === 3 || JSON.parse(row.status).value === 2 " v-hasPermi="['business:marketing:off']" type="text" @click="setStatus(row, 'off')">关闭</el-button>
+          <el-button v-if=" JSON.parse(row.status).value === 0 " v-hasPermi="['business:marketing:remove']" class="del" type="text" @click="del(row)">删除</el-button>
+          <el-button v-hasPermi="['business:marketing:copy']" type="text" @click="MarketingCopy(row.id,row.title)">复制</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" :ids="ids" @close="activityTableVisible = false" v-if="activityTableVisible"></activity-table>
+  </div>
+</template>
+<script>
+import { getMarketingList, delMarketing, setMarketingStatus, setMarketingStatusOff, ticketMarketingExport, getMarketingCopy } from '@/api/business/marketing'
+import ActivityTable from "./components/ActivityTable";
+export default {
+  name: 'groupLottery',
+  components:{
+    ActivityTable,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      tableData: [],
+      queryParams: {},
+      total: 0,
+      ids: {},
+      activityTableVisible: false,
+      marketingStatusList: []
+    }
+  },
+  created() {
+    // this.getList(true)
+    // this.getMarketingStatus()
+  },
+  methods: {
+    getList(reset) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+      if (reset) {
+        this.queryParams = { pageNum: 1, pageSize: 10 }
+      }
+      getMarketingList('pageNum='+this.queryParams.pageNum + '&pageSize='+this.queryParams.pageSize+'&', this.queryParams).then(res => {
+        this.loading = false
+        if (res.code === 0) {
+          this.tableData = res.rows
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    getMarketingStatus(){
+      this.getDicts('marketing_status').then(res=>{
+        this.marketingStatusList = res.data
+      })
+    },
+    setStatus(item, status) {
+      this.$confirm(`确认${status === 'on' ? '开启' : '关闭'}活动 “${item.title}” 吗?`, `${status === 'on' ? '开启' : '关闭'}活动`, {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        if (status === 'on'){
+          setMarketingStatus(item.id).then(res => {
+            if (res.code === 0) {
+              this.$message.success('开启已完成!')
+              this.getList()
+            }
+          })
+        }else{
+          setMarketingStatusOff(item.id).then(res => {
+            if (res.code === 0) {
+              this.$message.success('关闭已完成!')
+              this.getList()
+            }
+          })
+        }
+      })
+    },
+    del(item) {
+      this.$confirm(`确认删除活动 “${item.title}” 吗?`, '删除活动', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        delMarketing(item.id).then(res => {
+          if (res.code === 0) {
+            this.$message.success('操作已完成!')
+            this.getList()
+          }
+        })
+      })
+    },
+    MarketingCopy(id,title) {
+      this.$confirm(`确认复制活动 “${title}” 吗?`, '复制活动', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        getMarketingCopy(id).then(res => {
+          if (res.code === 0) {
+            this.$message.success('操作已完成!')
+            this.getList()
+          }
+        })
+      })
+    },
+
+    // 导出订单
+    handleExportDraw() {
+      this.$confirm("是否确认导出活动数据?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.vloading = this.$loading({
+            lock: true,
+            text: "正在导出活动数据.....",
+            background: "rgba(0, 0, 0, 0.7)",
+          });
+          return ticketMarketingExport(this.queryParams);
+        })
+        .then((response) => {
+          this.vloading.close();
+          this.download(response.msg);
+        })
+        .catch(() => {
+          this.vloading.close();
+        });
+    },
+  }
+}
+</script>

+ 1 - 1
src/views/business/recovery/index.vue

@@ -60,7 +60,7 @@
       <el-table-column label="商品名称" prop="title" min-width="95" align="center" />
       <el-table-column label="商品规格" prop="properties" min-width="95" align="center" >
         <template slot-scope="{row}">
-          <div v-if="row.properties">{{row.properties}}</div>
+          <div v-if="row.properties">{{row.properties || "--" }}</div>
           <div v-else>--</div>
         </template>
 

+ 59 - 1
src/views/business/salesite/components/AddCreate.vue

@@ -1,9 +1,38 @@
 <template>
   <el-dialog title="编辑门店名称" :visible.sync="dialogVisible" width="750px" :append-to-body="true" :before-close="close" :destroy-on-close="true" :close-on-click-modal="false">
     <el-form ref="form" :model="form" :rules="rules" label-width="120px" style="max-height: 375px;overflow: auto;">
+      <el-form-item label="上级渠道" prop="parentId" style="width: 60%;margin: 40px 0">
+        <el-select
+          v-model="form.parentId"
+          placeholder="请选择上级渠道"
+          style="width: 100%;"
+          filterable
+          clearable
+          :filter-method="dataFilter"
+        >
+          <el-option
+            v-for="(item) in channelList"
+            :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="门店名称" prop="name" style="width: 60%;margin: 40px 0">
         <el-input v-model="form.name" placeholder="例如xxxx店, 对用户可见" />
       </el-form-item>
+      <el-form-item label="手机号码" prop="mobile" style="width: 60%;margin: 40px 0">
+        <el-input
+          v-model="form.mobile"
+          placeholder="请输入手机号码"
+          clearable
+          size="small"
+        />
+      </el-form-item>
       <el-form-item label="关闭分佣:">
         <el-switch v-model="form.commFlag" :active-value="1" :inactive-value="0" />
         <div class="tip">开启后,购买线上票不分佣(渠道,门店,推广员)</div>
@@ -18,6 +47,7 @@
 </template>
 <script>
 import { updateSaleSite, getSaleSiteDetail } from "@/api/admin/salesite";
+import { listAllChannel } from "@/api/admin/channel";
 export default {
   props: {
     dialogVisible: {
@@ -33,6 +63,8 @@ export default {
       form: {
         name: "",
         commFlag: 0,
+        mobile: "",
+        parentId: null,
       },
       // 表单校验
       rules: {
@@ -41,9 +73,14 @@ export default {
         ],
       },
       //招商推广宣传图
-      picture: []
+      picture: [],
+      // 上级渠道列表
+      channelList:[],
     };
   },
+  mounted() {
+    this.getChannelList()
+  },
   created() {
     // 是编辑
     if (this.editId) {
@@ -51,11 +88,32 @@ export default {
     }
   },
   methods: {
+    // 获取上级渠道下拉列表
+    getChannelList(){
+      listAllChannel().then(response => {
+         this.channelList = response.data || [];
+         this.channelCopyList = response.data || [];
+      });
+    },
+    dataFilter(val) {
+      if (val) { //val存在
+        this.channelList = this.channelCopyList.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.channelList = this.channelCopyList;
+      }
+    },
     getDetail() {
       this.loading = true;
       getSaleSiteDetail(this.editId).then(res => {
         this.form.name = res.data.name
         this.form.commFlag = res.data.commFlag
+        this.form.mobile = res.data.mobile
+        this.form.parentId = res.data.parentId
         this.loading = false
       }).catch(() => {
         this.loading = false;

+ 25 - 2
src/views/business/salesite/index.vue

@@ -192,6 +192,12 @@
             <span v-if="getValue(scope.row.status) == 1"> 停用</span>
             <span v-if="getValue(scope.row.status) == 2"> 启用</span>
           </el-button>
+          <el-button
+            size="mini"
+            type="text"
+            @click="changeUpdate(scope.row)" v-if="scope.row.isTransform"
+            v-hasPermi="['business:salesite:edit']"
+          >转换角色</el-button>
          <!-- <el-switch
             style="margin-left: 9px;"
             v-model="scope.row.statusV"
@@ -267,9 +273,9 @@
 </template>
 
 <script>
-import { listAllChannel} from "@/api/admin/channel";
 import { listAreaByPid} from "@/api/admin/area";
 import { listSaleSite, updateSaleSiteStatus,salesiteOrderExport,salesiteDownload,salesiteImport } from "@/api/admin/salesite";
+import { listAllChannel, salesiteTransform } from "@/api/admin/channel";
 import SiteCreate from './components/Create'
 import AddSiteCreate from './components/AddCreate'
 import SiteDetail from './components/Detail'
@@ -277,7 +283,7 @@ export default {
   name: "Salesite",
   components: {
     AddSiteCreate,
-    SiteDetail
+    SiteDetail,
   },
   data() {
     return {
@@ -510,6 +516,23 @@ export default {
       this.createShow = true
     },
 
+    // 转换身份
+    changeUpdate(row) {
+      this.$confirm('确认要转换成渠道角色吗?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          var params={
+            channelId: row.channelId,
+          }
+          return salesiteTransform(params);
+        }).then(() => {
+          this.msgSuccess("转换成功");
+          this.getList()
+        });
+    },
+
     // 保存后的操作
     submitSuccess(){
       this.getList();

+ 22 - 1
src/views/business/ticket/create.vue

@@ -39,7 +39,8 @@
               <template slot="append">元</template>
             </el-input>
           </el-form-item>
-          <el-form-item label="售价" prop="salePrice">
+          
+          <el-form-item label="售价" prop="salePrice1" v-if="form.type == 'online' && form.saleChannelType == 2">
             <el-input
               v-model="form.salePrice"
               style="width: 240px"
@@ -49,6 +50,17 @@
               <template slot="append">元</template>
             </el-input>
           </el-form-item>
+          <el-form-item label="售价" prop="salePrice" v-else>
+            <el-input
+              v-model="form.salePrice"
+              style="width: 240px"
+              size="small"
+              placeholder="请输入售价"
+            >
+              <template slot="append">元</template>
+            </el-input>
+          </el-form-item>
+          <div class="tip" v-if="form.type == 'online'">线上盲票指定门店后可为0或不填,不填时默认处理为0</div>
           <el-form-item label="预付售票价" prop="prePrice">
             <el-input
               v-model="form.prePrice"
@@ -306,6 +318,15 @@ export default {
             trigger: ["blur", "change"],
           },
         ],
+        salePrice1: [
+          // { required: true, message: "请输入售价", trigger: "blur" },
+          {
+            pattern:
+              /^([0-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
+            message: "请输入合法的金额数字,最多两位小数",
+            trigger: ["blur", "change"],
+          },
+        ],
         prePrice: [
           { required: true, message: "请输入预付售票价", trigger: "blur" },
           {

+ 175 - 0
src/views/order/groupLotteryOrder/components/ExpressEdit.vue

@@ -0,0 +1,175 @@
+<template>
+  <div>
+    <el-dialog
+      title="修改快递信息"
+      :visible.sync="editShow"
+      width="500px"
+      :before-close="close"
+    >
+      <el-form
+        :model="shipForm"
+        ref="shipForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item label="配送方式:" prop="deliveryId">
+          <el-radio @change="radioDistribution" v-model="shipForm.deliveryType" label="1">快递发货</el-radio>
+          <el-radio @change="radioDistribution" v-model="shipForm.deliveryType" label="2">无需物流</el-radio>
+        </el-form-item>
+
+        <el-form-item v-if="shipForm.deliveryType == 1"  label="快递单号:" prop="deliveryFlowId">
+          <el-input
+            v-model="shipForm.deliveryFlowId"
+            @blur="InputBlur()"
+            placeholder="输入快递单号"
+            clearable
+            size="small"
+            style="width: 300px"
+          />
+        </el-form-item>
+        <el-form-item v-if="shipForm.deliveryType == 1"  label="快递公司:" prop="deliveryId">
+          <el-select
+            v-model="shipForm.deliveryId"
+            placeholder="请选择快递公司"
+            clearable
+            size="small"
+            style="width: 300px"
+          >
+            <el-option
+              v-for="item in companyData"
+              :key="item.areaId"
+              :label="item.companyName"
+              :value="item.deliveryId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <!-- 按钮 -->
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" :disabled="loading" @click="saveClick"
+          >确 定</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import CustomFieldsMixin from "@/mixins/CustomFields";
+import { companyList, channelOrderShipUpdate, automaticRecognition} from "@/api/business/order";
+export default {
+  mixins: [CustomFieldsMixin],
+  props: {
+    // 发货弹框显示
+    editShow: {
+      type: Boolean,
+      default: false,
+    },
+    // 订单详情
+    goodsInfo: {
+      type: Object,
+      default: {},
+    },
+  },
+  data() {
+    return {
+      loading: false,
+      shipForm: {
+        deliveryId: "",
+        deliveryFlowId: "",
+        deliveryType: "1",
+      },
+      // 快递下拉列表
+      companyData: [],
+      rules: {
+        deliveryId: [
+          { required: false, message: "请选择快递公司", trigger: "change" },
+        ],
+        deliveryFlowId: [
+          { required: false, message: "请输入快递单号", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  created() {
+    this.getCompanyList();
+    this.getFormData()
+  },
+  methods: {
+    getFormData(){
+      this.shipForm.deliveryId = this.goodsInfo.deliveryId
+      this.shipForm.deliveryFlowId = this.goodsInfo.deliveryFlowId
+      this.shipForm.deliveryType = this.goodsInfo.deliveryFlowId?"1":"2"
+    },
+
+    // 关闭发货弹框
+    close() {
+      this.$emit("close");
+      this.loading = false;
+      this.$refs["shipForm"].resetFields();
+    },
+
+    //切换配送方式时清空另一个方式所选项
+    radioDistribution(){
+      if(this.shipForm.deliveryType == '2'){
+        this.shipForm.deliveryId = '';
+        this.shipForm.deliveryFlowId = '';
+      }
+    },
+
+    // 快递下拉列表
+    getCompanyList() {
+      companyList({}).then((res) => {
+        this.companyData = res.data;
+      });
+    },
+
+    //快递单号失去焦点时
+    InputBlur(){
+      if (this.shipForm.deliveryFlowId){
+        automaticRecognition(this.shipForm.deliveryFlowId).then((res)=>{
+          if (res.code == 0 && res.data){
+            this.shipForm.deliveryId = res.data.deliveryId
+          }
+        })
+      }
+    },
+
+    // 确认
+    saveClick() {
+      this.loading = true;
+      const subForm = this.$refs["shipForm"];
+      subForm.validate((valid) => {
+        if (valid) {
+          this.submitForm(this.shipForm);
+        } else {
+          this.loading = false;
+          // 提示第一个error
+          this.getFormErrorMessage(subForm);
+          return false;
+        }
+      });
+    },
+
+    // 提交
+    submitForm(form) {
+      let data = {
+        ...form,
+        orderId: this.goodsInfo.orderId,
+      };
+      channelOrderShipUpdate(data)
+        .then((res) => {
+          if (res.code == 0) {
+            this.msgSuccess("修改成功");
+            this.close();
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+<style scoped>
+</style>

+ 308 - 0
src/views/order/groupLotteryOrder/components/SendGoods.vue

@@ -0,0 +1,308 @@
+<template>
+  <div>
+    <el-dialog
+      title="订单发货"
+      :visible.sync="sendShow"
+      width="800px"
+      :before-close="close"
+    >
+      <el-form
+        :model="shipForm"
+        ref="shipForm"
+        :rules="rules"
+        label-width="100px"
+      >
+        <el-form-item label="订单号:">
+          <span>{{ goodsInfo.orderId }}</span>
+        </el-form-item>
+        <el-form-item label="收货地址:">
+          <span>{{
+            `${goodsInfo.receiver},${goodsInfo.tel},${goodsInfo.province}${goodsInfo.city}${goodsInfo.area}${goodsInfo.address}`
+          }}</span>
+        </el-form-item>
+        <el-form-item label="配送方式:">
+          <!--单选框-->
+          <el-radio @change="radioDistribution" v-model="shipForm.deliveryType" label="1">快递发货</el-radio>
+          <el-radio @change="radioDistribution" v-model="shipForm.deliveryType" label="2">无需物流</el-radio>
+
+        </el-form-item>
+        <el-form-item v-if="shipForm.deliveryType == 1" label="快递单号:" prop="deliveryFlowId">
+          <el-input
+            v-model="shipForm.deliveryFlowId"
+            @blur="InputBlur()"
+            placeholder="输入快递单号"
+            clearable
+            size="small"
+            style="width: 500px"
+          />
+        </el-form-item>
+        <el-form-item v-if="shipForm.deliveryType == 1"  label="快递公司:" prop="deliveryId">
+          <el-select
+            v-model="shipForm.deliveryId"
+            placeholder="请选择快递公司"
+            clearable
+            size="small"
+            style="width: 500px"
+          >
+            <el-option
+              v-for="item in companyData"
+              :key="item.areaId"
+              :label="item.companyName"
+              :value="item.deliveryId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="盲票组:">
+          <el-select
+            v-model="shipForm.boxId"
+            placeholder="请选择盲票组"
+            clearable
+            size="small"
+            style="width: 500px"
+          >
+            <el-option
+              v-for="item in channelList"
+              :key="item.areaId"
+              :label="item.title"
+              :value="item.boxId"
+            >
+              <div class="channel">
+                <div>{{ item.boxNo }}</div>
+                <div>{{ item.title }}</div>
+                <div>{{ item.orderNum }}包</div>
+              </div>
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="盲票包序号:">
+          <el-autocomplete
+            v-model="pkgNo"
+            :fetch-suggestions="querySearch"
+            placeholder="输入盲票包序号"
+            size="small"
+            :disabled="shipForm.boxId ? false : true"
+            style="width: 500px"
+            @select="handleSelect"
+          >
+            <template slot-scope="{ item }">
+              <div class="channel">
+                <div>{{ item.startSn }}至{{ item.endSn }}</div>
+                <div>{{ item.title }}</div>
+              </div>
+            </template>
+          </el-autocomplete>
+        </el-form-item>
+      </el-form>
+      <!-- 选中盲票组列表 -->
+      <div class="table">
+        <el-table ref="table" :data="list">
+          <el-table-column label="盲票组" prop="title" />
+          <el-table-column label="盲票包系列号范围" min-width="100">
+            <template slot-scope="{ row }">
+              <div>
+                <div>{{ row.startSn }}至{{ row.endSn }}</div>
+              </div>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="50">
+            <template slot-scope="scope">
+              <div>
+                <el-button
+                  type="text"
+                  size="small"
+                  @click="delList(scope.$index, scope.row)"
+                  >删除</el-button
+                >
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!-- 按钮 -->
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="close">取 消</el-button>
+        <el-button type="primary" :disabled="loading" @click="saveClick"
+          >确 定</el-button
+        >
+      </div>
+    </el-dialog>
+  </div>
+</template>
+<script>
+import CustomFieldsMixin from "@/mixins/CustomFields";
+import { companyList, ticketPkgList, channelOrderShip, automaticRecognition} from "@/api/business/order";
+export default {
+  mixins: [CustomFieldsMixin],
+  props: {
+    // 发货弹框显示
+    sendShow: {
+      type: Boolean,
+      default: false,
+    },
+    // 订单详情
+    goodsInfo: {
+      type: Object,
+      default: {},
+    },
+    // 盲票组下拉列表
+    channelList: {
+      type: Array,
+      default: [],
+    },
+  },
+  created() {
+    this.getCompanyList();
+  },
+  data() {
+    return {
+      loading: false,
+      shipForm: {
+        deliveryId: "",
+        deliveryFlowId: "",
+        boxId: "",
+        deliveryType:"1",//物流配送方式单选框
+      },
+      // 快递下拉列表
+      companyData: [],
+      // 盲票组序列号
+      pkgNo: "",
+      // 选中盲票组列表
+      list: [],
+      rules: {
+        deliveryId: [
+          { required: true, message: "请选择快递公司", trigger: "change" },
+        ],
+        deliveryFlowId: [
+          { required: true, message: "请输入快递单号", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  methods: {
+    // 关闭发货弹框
+    close() {
+      this.$emit("close");
+      this.loading = false;
+      this.list = [];
+      this.shipForm.boxId = "";
+      this.$refs["shipForm"].resetFields();
+      this.shipForm.deliveryType = "1";
+    },
+
+    //切换配送方式时清空另一个方式所选项
+    radioDistribution(){
+      if(this.shipForm.deliveryType == '2'){
+        this.shipForm.deliveryId = '';
+        this.shipForm.deliveryFlowId = '';
+        this.shipForm.boxId = "";
+        this.list = [];
+      }
+      if(this.shipForm.deliveryType == '1'){
+        this.shipForm.boxId = "";
+        this.list = [];
+      }
+    },
+
+    // 快递下拉列表
+    getCompanyList() {
+      companyList({}).then((res) => {
+        this.companyData = res.data;
+      });
+    },
+
+    //快递单号失去焦点时
+    InputBlur(){
+      if (this.shipForm.deliveryFlowId){
+        automaticRecognition(this.shipForm.deliveryFlowId).then((res)=>{
+          if (res.code == 0 && res.data){
+            this.shipForm.deliveryId = res.data.deliveryId
+          }
+        })
+      }
+    },
+
+    // 查询盲票组序列号
+    querySearch(queryString, cb) {
+      ticketPkgList({
+        orderId: this.goodsInfo.orderId,
+        boxId: this.shipForm.boxId,
+        pkgNo: this.pkgNo,
+      }).then((res) => {
+        cb(res.data);
+      });
+    },
+
+    // 选中盲票组序列号
+    handleSelect(item) {
+      let index = this.list.findIndex(ele=>{
+        return item.pkgId == ele.pkgId
+      })
+      if(index != -1){
+        this.msgError("当前票包已选!");
+        return
+      }
+      this.list.push(item);
+    },
+
+    // 删除选中盲票组序列号
+    delList(index, row) {
+      this.list.splice(index, 1);
+    },
+
+    // 确认
+    saveClick() {
+      this.loading = true;
+      const subForm = this.$refs["shipForm"];
+      subForm.validate((valid) => {
+        if (valid) {
+          this.submitForm(this.shipForm);
+        } else {
+          this.loading = false;
+          // 提示第一个error
+          this.getFormErrorMessage(subForm);
+          return false;
+        }
+      });
+    },
+
+    // 提交
+    submitForm(form) {
+      let ids = this.list.map((item) => item.pkgId);
+      if (!ids.length) {
+        this.msgError("请选择发货的票包");
+        this.loading = false;
+        return;
+      }
+      if (this.goodsInfo.pkgNum != ids.length) {
+        this.msgError(
+          `应发${this.goodsInfo.pkgNum}包,实际选中${ids.length}包`
+        );
+        this.loading = false;
+        return;
+      }
+      let data = {
+        ...form,
+        orderId: this.goodsInfo.orderId,
+        pkgIds: ids,
+      };
+      channelOrderShip(data)
+        .then((res) => {
+          if (res.code == 0) {
+            this.msgSuccess("发货成功");
+            this.close();
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+  },
+};
+</script>
+<style scoped>
+.channel {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+</style>

+ 330 - 0
src/views/order/groupLotteryOrder/detail.vue

@@ -0,0 +1,330 @@
+<template>
+  <div class="app-container">
+    <!-- 订单信息 -->
+    <el-row :gutter="10">
+      <el-col :span="22" :offset="1">
+        <div class="info-title">订单信息</div>
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title">订单编号:{{ info.orderId }}</div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 24, offset: 0}">
+          <div class="title">订单类型:门店订单</div>
+        </el-col>
+        <el-col :span="8" :xs="{span: 24, offset: 0}">
+          <div class="title">下单时间:{{ parseTime(info.createdTime) }}</div>
+        </el-col>
+      </el-col>
+    </el-row>
+    <!-- 卖家信息 -->
+    <el-row :gutter="10" >
+      <el-col :span="22" :offset="1">
+        <div class="info-title">买家信息</div>
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title">门店:{{ info.channel && info.channel.name }}</div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 24, offset: 0}">
+          <div class="title">上级渠道:{{ info.channel && info.channel.parentName }}</div>
+        </el-col>
+        <el-col :span="8" :xs="{span: 24, offset: 0}">
+          <div class="title">收货人:{{ info.receiver || "--" }}</div>
+        </el-col>
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title">联系电话:{{ info.tel || "--" }}</div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 24, offset: 0}">
+          <div class="title">收货地址:{{
+              `${info.province || "--"}${info.city || "--"}${
+                info.area || "--"
+              }${info.address || "--"}`
+            }}
+          </div>
+        </el-col>
+      </el-col>
+    </el-row>
+    <!-- 买家留言 -->
+    <el-row :gutter="10">
+      <el-col :span="22" :offset="1">
+        <div class="info-title">备注信息</div>
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title">买家留言:{{ info.memo || "--" }}</div>
+        </el-col>
+      </el-col>
+    </el-row>
+    <!--  订单状态  -->
+    <el-row :gutter="10">
+      <el-col :span="22" :offset="1">
+        <div class="info-title">订单状态</div>
+
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title">订单状态:{{ status.value == 2 ? "已发货" : (status.desc || "--") }}</div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 18, offset: 0}">
+          <div class="title" v-if="status.value === 2 || status.value === 3">
+            发货时间:{{ parseTime(info.deliveryTime) || "--" }}
+          </div>
+        </el-col>
+        <el-col :span="8" :xs="{span: 4, offset: 0}">
+          <div class="edit-express" v-if="status.value === 2" @click="editExpress">修改</div>
+        </el-col>
+        <el-button
+          v-if="status.value === 1"
+          v-hasPermi="['business:ticket:on']"
+          type="primary"
+          @click="toGoods()"
+        >发货
+        </el-button
+        >
+        <el-col :span="8" :offset="1" :xs="{span: 24, offset: 0}">
+          <div class="title" v-if="status.value === 2 || status.value === 3">配送方式:{{ "快递发货" || "--" }}</div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 24, offset: 0}">
+          <div class="title" v-if="status.value === 2 || status.value === 3">
+            快递公司:{{ (delivery && delivery.companyName) || "--" }}
+          </div>
+        </el-col>
+        <el-col :span="7" :xs="{span: 24, offset: 0}">
+          <div class="title" v-if="status.value === 2 || status.value === 3">快递单号:{{
+              info.deliveryFlowId || "--"
+            }}
+          </div>
+        </el-col>
+      </el-col>
+    </el-row>
+    <br>
+    <el-row :gutter="10">
+      <el-col :span="22" :offset="1">
+        <!-- 商品信息 -->
+        <div class="info">
+          <div class="info-title">商品信息</div>
+          <div class="info-table">
+            <el-table :data="list">
+              <el-table-column label="商品信息">
+                <div slot-scope="{ row }" class="flex">
+                  <el-image
+                    style="width: 100px; height: 100px"
+                    :src="row.picUrl"
+                    :preview-src-list="[row.picUrl]"
+                  />
+                  <div class="txt">{{ row.title }}</div>
+                </div>
+              </el-table-column>
+              <el-table-column label="单价(元)">
+                <template slot-scope="{ row }">
+                  <div>{{ $numberFormat(row.pkgSalePrice) }}</div>
+                </template>
+              </el-table-column>
+              <el-table-column label="数量" prop="orderNum">
+                <template slot-scope="{ row }">
+                  <div>{{ row.orderNum }}包</div>
+                </template>
+              </el-table-column>
+              <el-table-column label="小计(元)">
+                <template slot-scope="{ row }">
+                  <div>{{ $numberFormat(row.pkgSalePrice * row.orderNum) }}</div>
+                </template>
+              </el-table-column>
+              <el-table-column
+                v-if="status.value === 2 || status.value === 3"
+                label="附加信息"
+                min-width="150"
+              >
+                <template slot-scope="{ row }">
+                  <div>
+                    序列号:
+                    <div v-for="(item, index) in row.detailList" :key="index">
+                      {{ item.startSn }} 至 {{ item.endSn }}
+                    </div>
+                  </div>
+                </template>
+              </el-table-column>
+            </el-table>
+          </div>
+          <div class="info-amt">
+            <div class="info-amt-price">
+              <span>运费:</span>{{ $numberFormat(info.freightAmt) }}元
+            </div>
+            <div class="info-amt-price">
+              <span>共计金额:</span>{{ $numberFormat(info.payAmt) }}元
+            </div>
+          </div>
+        </div>
+      </el-col>
+    </el-row>
+
+    <!-- 发货 -->
+    <send-goods
+      :send-show="goodsShow"
+      :goods-info="info"
+      :channel-list="boxData"
+      @close="close"
+    />
+
+    <!-- 修改快递信息 -->
+    <express-edit
+      v-if="editShow"
+      :edit-show="editShow"
+      :goods-info="info"
+      @close="close"
+    />
+
+
+  </div>
+</template>
+<script>
+import {orderDetail, boxList} from "@/api/business/order";
+import {publicFileGetUrl} from "@/api/common";
+import {accMul} from "@/utils/util";
+import SendGoods from "./components/SendGoods";
+import ExpressEdit from "./components/ExpressEdit";
+
+export default {
+  name: "ChannelDetail",
+  components: {
+    SendGoods,
+    ExpressEdit,
+  },
+  data() {
+    return {
+      // 订单ID
+      orderId: "",
+      // 订单详情
+      info: {},
+      // 订单状态
+      status: {},
+      // 物流信息
+      delivery: {},
+      // 商品列表
+      list: [],
+      // 发货弹框显示
+      goodsShow: false,
+      // 盲票组列表
+      boxData: [],
+      // 修改快递信息弹框
+      editShow: false,
+    };
+  },
+  created() {
+    this.orderId = this.$route.query.id;
+    this.getDetail();
+    this.getChannelList();
+  },
+  activated() {
+    const orderId = this.$route.query.id;
+    if (orderId != null && orderId != this.orderId) {
+      this.orderId = orderId;
+      this.getDetail();
+      this.getChannelList();
+    }
+  },
+  methods: {
+    // 盲票组列表
+    getChannelList(row) {
+      boxList({orderId: this.orderId}).then((res) => {
+        this.boxData = res.data;
+      });
+    },
+
+    // 订单详情
+    getDetail() {
+      orderDetail({orderId: this.orderId}).then((res) => {
+        if (res.code == 0) {
+          this.info = res.data;
+          this.status = JSON.parse(res.data.status);
+          this.delivery = res.data.deliveryCompany;
+          res.data.items.forEach((item) => {
+            let picUrlArr = item.picUrl.split(",");
+            item.picUrl = publicFileGetUrl + picUrlArr[0];
+          });
+          this.list = res.data.items;
+        }
+      });
+    },
+
+    // 点击发货
+    toGoods() {
+      this.goodsShow = true;
+    },
+
+    // 发货弹框关闭
+    close() {
+      this.goodsShow = false;
+      this.editShow = false;
+      this.getDetail();
+    },
+
+    // 修改快递信息
+    editExpress() {
+      this.editShow = true;
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+.title {
+  line-height: 30px;
+  text-align: left;
+}
+.edit-express {
+  color: #409eff;
+  cursor: pointer;
+}
+
+.info {
+  margin-bottom: 10px;
+
+  &-title {
+    font-size: 14px;
+    margin-bottom: 10px;
+    font-weight: bold;
+  }
+
+  &-item {
+    padding-left: 50px;
+
+    &-content {
+      display: flex;
+
+      &-one {
+        display: flex;
+        margin-bottom: 10px;
+
+        .title {
+          line-height: 22px;
+          //width: 100px;
+        }
+
+        .edit-express {
+          color: #409eff;
+          cursor: pointer;
+        }
+
+        .txt {
+          line-height: 22px;
+          //width: 200px;
+        }
+      }
+    }
+  }
+
+  &-amt {
+    margin-top: 10px;
+
+    &-price {
+      span {
+        display: inline-block;
+        width: 80px;
+        margin-bottom: 20px;
+      }
+    }
+  }
+}
+
+.flex {
+  display: flex;
+  align-items: center;
+
+  .txt {
+    margin-left: 20px;
+  }
+}
+</style>

+ 458 - 0
src/views/order/groupLotteryOrder/index.vue

@@ -0,0 +1,458 @@
+<template>
+  <div class="app-container">
+    <el-form
+      :model="queryParams"
+      ref="queryForm"
+      :inline="true"
+      v-show="showSearch"
+      label-width="90px"
+    >
+      <el-form-item label="活动名称"  prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="活动名称"
+          clearable
+          size="small"
+          style="width: 240px"
+          @change="pageParams.pageNum = 1;handleQuery()"
+        />
+      </el-form-item>
+
+      <el-form-item label="奖品类型" prop="orderId">
+        <el-select v-model="queryParams.type" placeholder="请选择奖品类型" style="width: 100%;" clearable :filter-method="dataFilter" @change="pageParams.pageNum = 1;handleQuery()" >
+          <el-option label="全部" value="" />
+          <el-option v-for="(item,index) in typeList"  :label="item.dictLabel" :value="Number(item.dictValue)" :key="index"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="订单号" prop="orderId">
+        <el-input
+          v-model="queryParams.orderId"
+          placeholder="输入订单编号"
+          clearable
+          size="small"
+          style="width: 240px"
+          @change="pageParams.pageNum = 1;handleQuery()"
+        />
+      </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.channelId"
+          placeholder="可输入门店名称/手机号码搜索"
+          clearable
+          filterable
+          size="small"
+          style="width: 240px"
+          @change="handleQuery"
+        >
+          <el-option
+            v-for="item in merchantArr"
+            :key="item.areaId"
+            :label="item.areaName"
+            :value="item.areaId"
+          />
+        </el-select>
+      </el-form-item> -->
+      <el-form-item label="下单时间">
+        <el-date-picker
+          v-model="tradeTimeArr"
+          type="datetimerange"
+          size="small"
+          value-format="timestamp"
+          range-separator="至"
+          start-placeholder="时间选择"
+          end-placeholder="时间选择"
+          @change="tardeTime"
+        >
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item>
+        <el-button
+          type="primary"
+          icon="el-icon-search"
+          size="mini"
+          @click="pageParams.pageNum = 1;handleQuery()"
+          >搜索</el-button
+        >
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
+          >重置</el-button
+        >
+      </el-form-item>
+    </el-form>
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleOrderExport"
+          v-hasPermi="['order:channel:export']"
+          >导出订单</el-button
+        >
+      </el-col>
+      <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar>
+    </el-row>
+    <!-- 订单状态 -->
+    <el-tabs type="card" v-model="state" @tab-click="handleClick">
+      <el-tab-pane label="全部订单" name="null"></el-tab-pane>
+      <el-tab-pane label="待付款" name="0"></el-tab-pane>
+      <el-tab-pane label="待发货" name="1"></el-tab-pane>
+      <el-tab-pane label="待收货" name="2"></el-tab-pane>
+      <el-tab-pane label="已收货" name="2"></el-tab-pane>
+      <el-tab-pane label="已完成" name="3"></el-tab-pane>
+      <el-tab-pane label="已关闭" name="-1"></el-tab-pane>
+    </el-tabs>
+    <!-- 列表 -->
+    <el-table ref="table" v-loading="loading" :data="list">
+      <el-table-column label="订单号" prop="orderId" min-width="80" />
+      <el-table-column label="奖品类型" prop="orderId" min-width="80" align="center">
+        <template slot-scope="{ row }">
+          <div>
+            <div v-if="row.type && JSON.parse(row.type).value == 1">普通票</div>
+            <div v-if="row.type && JSON.parse(row.type).value == 2" style="color: red">线下预付票</div>
+            <div v-if="row.type && JSON.parse(row.type).value == 3">线上预付票</div>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="数量" prop="pkgNum" min-width="65">
+        <template slot-scope="{ row }">
+          <div>{{ row.pkgNum }}包</div>
+        </template>
+      </el-table-column>
+      <el-table-column label="拼团金额" prop="orderId" min-width="80" />
+      <el-table-column label="收货人" prop="orderId" min-width="80" />
+      <el-table-column label="交易状态" prop="orderId" min-width="80" />
+      <el-table-column label="门店名称" prop="channelName" min-width="80" />
+      <el-table-column label="下单时间" min-width="100">
+        <template slot-scope="{ row }">
+          <div>
+            {{ parseTime(row.createdTime) }}
+          </div>
+        </template>
+      </el-table-column>
+
+
+
+      <el-table-column label="订单状态" align="center">
+        <template slot-scope="{ row }">
+          <div>
+            <el-tag :type="row.status.value === 1 ? 'success' : 'info'" v-if="row.status.value !== 2">{{
+              row.status.desc
+            }}</el-tag>
+            <el-tag type="info" v-else>已发货</el-tag>
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="80">
+        <template slot-scope="{ row }">
+          <div>
+            <el-button
+              v-hasPermi="['order:channel:query']"
+              type="text"
+              @click="getDetail(row)"
+            >查看详情</el-button>
+            <el-button
+              v-if="row.status.value === 1"
+              type="text"
+              @click="cancellationOrder(row)"
+            >取消订单</el-button>
+            <el-button
+              v-if="row.status.value === 1"
+              v-hasPermi="['order:channel:ship']"
+              type="text"
+              @click="toGoods(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"
+    />
+
+    <!-- 发货 -->
+    <send-goods
+      :send-show="goodsShow"
+      :goods-info="goodsInfo"
+      :channel-list="boxData"
+      @close="close"
+    />
+  </div>
+</template>
+<script>
+import { getOrderList, companyList, boxList, channelOrderExport, removeChannelOrder} from "@/api/business/order";
+import { listAllSaleSite} from "@/api/admin/salesite";
+import { publicFileGetUrl } from "@/api/common";
+import SendGoods from "./components/SendGoods";
+export default {
+  name: "Channel",
+  components: {
+    SendGoods,
+  },
+  data() {
+    return {
+      loading: false,
+      showSearch: true,
+      // 筛选
+      queryParams: {
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        channelId: "",
+        status: null,
+      },
+      // 分页
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10,
+      },
+      // 总条数
+      total: 0,
+      list: [],
+      // 门店
+      merchantArr: [],
+      // 下单时间
+      tradeTimeArr: [],
+      // 订单列表状态
+      state: "null",
+      // 弹框显示
+      goodsShow: false,
+      // 订单详情
+      goodsInfo: {},
+      // 盲票组下拉列表
+      boxData: [],
+      siteList:[],
+      siteCopyList:[],
+      typeList: []
+    };
+  },
+  mounted() {
+    // this.getSaleSiteList()
+  },
+  created() {
+    // this.getList();
+    // this.getTypeList()
+  },
+  methods: {
+    // 订单列表
+    getList() {
+      this.loading = true;
+      getOrderList(
+        "pageNum=" +
+          this.pageParams.pageNum +
+          "&pageSize=" +
+          this.pageParams.pageSize +
+          "&",
+        this.queryParams
+      )
+        .then((res) => {
+          this.loading = false;
+          if (res.code == 0) {
+            res.rows.forEach((item) => {
+              let items = item.items;
+              items.forEach((item) => {
+                let picUrlArr = item.picUrl.split(",");
+                item.picUrl = publicFileGetUrl + picUrlArr[0];
+              });
+              item.status = JSON.parse(item.status);
+            });
+            this.total = res.total;
+            this.list = res.rows;
+          }
+        })
+        .catch(() => {
+          this.loading = false;
+        });
+    },
+
+    //订单类型筛选列表
+    getTypeList(){
+      this.getDicts('channel_order_type').then(res=>{
+        this.typeList = res.data
+      })
+    },
+
+    // 盲票组列表
+    getBoxList(row) {
+      boxList({ orderId: row.orderId }).then((res) => {
+        this.boxData = 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;
+      }
+    },
+
+    //搜索
+    handleQuery() {
+      this.siteList = this.siteCopyList;
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+
+    // 重置
+    resetQuery() {
+      this.queryParams = {
+        title: "",
+        orderId: "",
+        startTime: "",
+        endTime: "",
+        channelId: "",
+        status: null,
+      };
+      this.state = "null"
+      this.tradeTimeArr = [];
+      this.getList();
+    },
+
+    // 选择下单时间
+    tardeTime(e) {
+      if (e) {
+        this.queryParams.startTime = e[0];
+        this.queryParams.endTime = e[1];
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      } else {
+        this.queryParams.startTime = "";
+        this.queryParams.endTime = "";
+        this.pageParams.pageNum = 1
+        this.handleQuery();
+      }
+    },
+
+    // 订单切换
+    handleClick(e) {
+      this.queryParams.status = Number(e.name);
+      this.getList();
+    },
+
+    // 查看详情
+    getDetail(row) {
+      this.$router.push({ name: "groupLotteryOrderDetail", query: { id: row.orderId } });
+    },
+
+    // 点击发货
+    toGoods(row) {
+      this.goodsShow = true;
+      this.goodsInfo = row;
+      this.getBoxList(row);
+    },
+
+    //取消订单
+    cancellationOrder(row){
+      this.$confirm('确定要取消订单吗?取消后实付金额将原路返回', '取消订单', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.vloading = this.$loading({
+          lock: true,
+          text: "正在取消订单.....",
+          background: "rgba(0, 0, 0, 0.7)",
+        });
+        let data = {
+          orderId:row.orderId
+        }
+        return  removeChannelOrder(data)
+      }).then(()=>{
+        this.vloading.close();
+        this.getList()
+        this.$message({
+          type: 'success',
+          message: '取消订单成功!'
+        })
+      }).catch(() => {
+        this.vloading.close();
+      });
+    },
+
+    // 关闭发货弹框
+    close() {
+      this.goodsShow = false;
+      this.getList();
+    },
+
+    // 导出订单
+    handleOrderExport() {
+      this.$confirm("是否确认导出订单?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.vloading = this.$loading({
+            lock: true,
+            text: "正在导出订单.....",
+            background: "rgba(0, 0, 0, 0.7)",
+          });
+          return channelOrderExport(this.queryParams);
+        })
+        .then((response) => {
+          this.vloading.close();
+          this.download(response.msg);
+        })
+        .catch(() => {
+          this.vloading.close();
+        });
+    },
+  },
+};
+</script>
+<style lang="scss" scoped>
+::v-deep .el-tabs--border-card > .el-tabs__content {
+  padding: 0;
+}
+.el-button {
+  margin-left: 0;
+}
+</style>