From 99e7c80d1f32d79977f3bf5357d85207fc560f53 Mon Sep 17 00:00:00 2001
From: liwei <liwei@singsingenglish.com>
Date: Wed, 10 Jul 2019 17:09:22 +0800
Subject: [PATCH] liwei

---
 src/components/channelTransList/index.vue     | 131 ++++-
 src/components/class/index.vue                | 157 ++----
 src/components/logistics/index.vue            | 458 ++++++++++--------
 .../logistics/receiveInfoDialog.vue           |  70 +++
 src/components/marketStatistics/index.vue     | 236 ++++-----
 src/service/api.js                            |  13 +
 src/util/menuList.js                          |  37 +-
 7 files changed, 619 insertions(+), 483 deletions(-)
 create mode 100644 src/components/logistics/receiveInfoDialog.vue

diff --git a/src/components/channelTransList/index.vue b/src/components/channelTransList/index.vue
index 91d8a271..cde76021 100644
--- a/src/components/channelTransList/index.vue
+++ b/src/components/channelTransList/index.vue
@@ -6,7 +6,7 @@
       style="background:#fff;textAlign: center;color: #909399;padding: 10px 0;"
     >暂无数据</div>
     <el-form ref="searchFrom" :model="searchFrom" label-width="100px" inline v-if="list.length > 0">
-      <el-form-item label="进量日期">
+      <el-form-item label="起止日期">
         <el-date-picker
           v-model="searchFrom.payTime"
           type="datetimerange"
@@ -73,30 +73,52 @@
       <el-form-item>
         <div class="flexRow">
           <el-button type="primary" plain @click="getChannelTransList">搜索</el-button>
+          <el-button type="primary" plain @click="exportDataTable">导出</el-button>
         </div>
       </el-form-item>
     </el-form>
-
     <el-table
+      border
+      :span-method="objectSpanMethod"
       v-if="list.length > 0"
       :data="list"
       :style="{width: width+'px'}"
-      :default-sort="{prop: 'cur_date', order: 'descending'}"
     >
-      <el-table-column prop="cur_date" label="支付日期" sortable></el-table-column>
-      <el-table-column prop="invite_type" label="渠道类型" sortable></el-table-column>
+      <el-table-column prop="cur_date" label="进量日期"></el-table-column>
+      <el-table-column prop="invite_type" label="渠道类型"></el-table-column>
+      <!-- <el-table-column prop="watch_num" label="商品课时数"></el-table-column> -->
+      <el-table-column prop="periods_title" label="期数名称"></el-table-column>
+      <el-table-column prop="goods_name" label="商品名称"></el-table-column>
+      <el-table-column prop="squad" label="组ID"></el-table-column>
       <el-table-column prop="teacher_name" label="老师名称"></el-table-column>
+      <el-table-column prop="total_num" label="购买人数"></el-table-column>
+      <el-table-column prop="class_num" label="班级人数"></el-table-column>
       <el-table-column prop="teacher_friend_num" label="老师主动添加好友人数"></el-table-column>
       <el-table-column prop="user_friend_num" label="用户主动添加好友人数"></el-table-column>
+      <el-table-column prop="come_num" label="到课人数"></el-table-column>
+      <el-table-column prop="one_buy_num" label="一年课购买人数"></el-table-column>
+      <el-table-column prop="two_buy_num" label="两年课购买人数"></el-table-column>
+      <el-table-column prop="one_buy_money" label="一年课转化金额"></el-table-column>
+      <el-table-column prop="two_buy_money" label="两年课转化金额"></el-table-column>
+    </el-table>
+
+    <!-- <el-table v-if="list.length > 0" :data="list" :style="{width: width+'px'}">
+      <el-table-column prop="cur_date" label="进量日期"></el-table-column>
+      <el-table-column prop="invite_type" label="渠道类型"></el-table-column>
+      <el-table-column prop="watch_num" label="商品课时数"></el-table-column>
       <el-table-column prop="periods_title" label="期数名称"></el-table-column>
       <el-table-column prop="squad" label="组ID"></el-table-column>
-      <el-table-column prop="watch_num" label="商品课时数"></el-table-column>
+      <el-table-column prop="teacher_name" label="老师名称"></el-table-column>
+      <el-table-column prop="total_num" label="购买人数"></el-table-column>
       <el-table-column prop="class_num" label="班级人数"></el-table-column>
+      <el-table-column prop="teacher_friend_num" label="老师主动添加好友人数"></el-table-column>
+      <el-table-column prop="user_friend_num" label="用户主动添加好友人数"></el-table-column>
       <el-table-column prop="come_num" label="到课人数"></el-table-column>
       <el-table-column prop="one_buy_num" label="年课购买人数"></el-table-column>
+      <el-table-column prop="two_buy_num" label="两年课购买人数"></el-table-column>
       <el-table-column prop="one_buy_money" label="一年课转化金额"></el-table-column>
       <el-table-column prop="two_buy_money" label="两年课转化金额"></el-table-column>
-    </el-table>
+    </el-table>-->
     <page
       v-if="list.length > 0"
       :nowPage="nowPage"
@@ -112,7 +134,8 @@ import {
   getTeacherListApi,
   getchannelTransListApi,
   getPeriodsApi,
-  getGoodsListApi
+  getGoodsListApi,
+  exportExcelApi
 } from "../../service/api";
 import page from "../framework/page";
 import { GOODSTYPE, CLASSSOURCE } from "../../util/wordbook";
@@ -175,6 +198,8 @@ export default {
           ];
         }
       },
+      propertyList: [],
+      spanArr: [],
       searchFrom: {
         payTime: [],
         start_at: "",
@@ -195,9 +220,66 @@ export default {
       ]
     };
   },
-
   components: { page },
   methods: {
+    exportDataTable() {
+      let json = {};
+      if (
+        this.searchFrom.start_at.length > 0 &&
+        this.searchFrom.end_at.length > 0
+      ) {
+        json.start_at = this.searchFrom.start_at;
+        json.end_at = this.searchFrom.end_at;
+      }
+      if (this.searchFrom.teacher_id) {
+        json.teacher_id = this.searchFrom.teacher_id;
+      }
+      if (this.searchFrom.invite_type.length > 0) {
+        json.invite_type = this.searchFrom.invite_type;
+      }
+      if (this.searchFrom.periods_id) {
+        json.periods_id = this.searchFrom.periods_id;
+      }
+      if (this.searchFrom.squad) {
+        json.squad = this.searchFrom.squad;
+      }
+      if (this.searchFrom.watch_num) {
+        json.watch_num = this.searchFrom.watch_num;
+      }
+      console.log("json======", json);
+      exportExcelApi("/api/admin/channel/class/list/export", json);
+    },
+    objectSpanMethod(data) {
+      if (this.propertyList.indexOf(data.column.property) > -1) {
+        if (
+          data.rowIndex === 0 ||
+          data.row.cur_date !== this.list[data.rowIndex - 1].cur_date
+        ) {
+          let rowspan = 1;
+          for (let i = data.rowIndex + 1; i < this.list.length; i++) {
+            if (data.row.cur_date === this.list[i].cur_date) {
+              rowspan++;
+            } else {
+              break;
+            }
+          }
+          return {
+            rowspan: rowspan,
+            colspan: 1
+          };
+        } else {
+          return {
+            rowspan: 0,
+            colspan: 0
+          };
+        }
+      } else {
+        return {
+          rowspan: 1,
+          colspan: 1
+        };
+      }
+    },
     handleItemChange(val) {
       getPeriodsApi({ goods_id: val[0], limit: 100 }).then(res => {
         res.list.forEach(i => {
@@ -320,20 +402,43 @@ export default {
       }
       getchannelTransListApi(json).then(res => {
         if (res) {
-          this.total = res.total;
           if (res.list && res.list.length > 0) {
-            this.list = res.list.map(item => {
+            this.total = res.total;
+            this.list = res.list.map((item, index) => {
+              item.index = index;
+              if (index == 0) {
+                this.spanArr.push(1);
+                this.pos = 0;
+              } else {
+                if (item.cur_date == res.list[index - 1].cur_date) {
+                  this.spanArr[this.pos] += 1;
+                  this.spanArr.push(0);
+                } else {
+                  this.spanArr.push(1);
+                  this.pos = index;
+                }
+              }
               item.squad = "T" + item.squad;
               let name =
                 item.invite_name && item.invite_name.length > 0
                   ? `(${item.invite_name})`
                   : "";
+              let goods_id =
+                item.goods_id && item.goods_id > 0
+                  ? `【${item.goods_id}】`
+                  : "";
+              let watch_num =
+                item.watch_num && item.watch_num > 0
+                  ? `【${item.watch_num}个课时】`
+                  : "";
               item.invite_type = `${item.invite_type}${name}`;
+              item.goods_name = `${goods_id}${item.goods_name}${watch_num}`;
               return item;
             });
+            for (let key in this.list[0]) {
+              this.propertyList.push(key);
+            }
             this.width = document.documentElement.clientWidth - 200;
-          } else {
-            this.list = [];
           }
         } else {
           this.list = [];
diff --git a/src/components/class/index.vue b/src/components/class/index.vue
index 8dac41f7..a102f5f8 100644
--- a/src/components/class/index.vue
+++ b/src/components/class/index.vue
@@ -29,7 +29,6 @@
         </el-form-item>
         <el-form-item label>
           <el-button type="primary" @click="getClassList">搜索</el-button>
-          <el-button type="success" @click="sendMsg">发送活动通知</el-button>
         </el-form-item>
         <el-form-item style="float: right">
           <el-button @click="onAdd" type="success" v-if="!$store.state.readonly">+添加班级</el-button>
@@ -323,127 +322,41 @@ export default {
         this.initQuery();
       });
     },
-    methods: {
-      sendMsg() {
-        if (this.title && this.title.title) {
-          this.$confirm("你将发送给" + this.title.title + "用户", "提示", {
-            confirmButtonText: "确定",
-            cancelButtonText: "取消",
-            type: "warning"
-          }).then(() => {
-            // console.log(this.selectedGoods)
-            postActiveNoticeApi(this.periods.id).then(res => {
-              this.noticeDialog = false;
-              this.$message({
-                type: "success",
-                message: "发送成功" + res.num + "个"
-              });
-            });
-          });
-        } else {
-          this.$message({
-            message: "请选择期数"
-          });
-        }
-      },
-      changeRow(data, b) {
-        if (b.indexOf(data) > -1) {
-          getClassStatisticsApi(data.periods_id, data.id).then(res => {
-            data.arrive_course_rate = res.arrive_course_rate;
-            data.watch_course_rate = res.watch_course_rate;
-            data.over_course_rate = res.over_course_rate;
-            data.work_rate = res.work_rate;
-            data.over_work_rate = res.over_work_rate;
-            data.clock_rate = res.clock_rate;
-            data.over_clock_rate = res.over_clock_rate;
-            data.transform_rate = res.transform_rate;
-          });
-        }
-      },
-      initQuery() {
-        let _query = this.$route.query;
-        if (_query && _query.goods_id && _query.periods_id) {
-          this.goods_id = _query.goods_id;
-          this.selectedGoods = [
-            parseInt(_query.goods_id),
-            parseInt(_query.periods_id)
-          ];
-          getPeriodsApi({ goods_id: this.selectedGoods[0], limit: 100 }).then(
-            res => {
-              res.list.forEach(i => {
-                i.name = i.title;
-              });
-              this.goodsList.find(i => {
-                return i.id === this.selectedGoods[0];
-              }).children = res.list;
-              let nowGoods = this.goodsList.find(i => {
-                return i.id === this.selectedGoods[0];
-              });
-              this.periods = nowGoods.children.find(i => {
-                return i.id === this.selectedGoods[1];
-              });
-              console.log(this.periods);
-              this.teacher_id = "";
-              this.getClassList();
-            }
-          );
-        } else {
-          getDefaultPeriodsApi().then(res => {
-            console.log(res);
-            //
-            if (res) {
-              this.goods_id = res.goods_id;
-              this.selectedGoods = [parseInt(res.goods_id), parseInt(res.id)];
-              getPeriodsApi({
-                goods_id: this.selectedGoods[0],
-                limit: 100
-              }).then(res => {
-                res.list.forEach(i => {
-                  i.name = i.title;
-                });
-                this.goodsList.find(i => {
-                  return i.id === this.selectedGoods[0];
-                }).children = res.list;
-                let nowGoods = this.goodsList.find(i => {
-                  return i.id === this.selectedGoods[0];
-                });
-                this.periods = nowGoods.children.find(i => {
-                  return i.id === this.selectedGoods[1];
-                });
-                this.teacher_id = "";
-                console.log(this.periods);
-
-                this.getClassList();
-              });
-            }
-          });
-        }
-        console.log(this.goodsList);
-      },
-      initPage() {
-        let json = {
-          page: 1,
-          limit: 100,
-          goods_type: "1,2"
-        };
-        getGoodsListApi(json).then(res => {
-          console.log(res);
-          res.list.forEach(i => {
-            i.name =
-              "[" +
-              i.id +
-              "]" +
-              "[" +
-              GOODSTYPE[i.goods_type] +
-              "]" +
-              "[" +
-              i.current_price / 100 +
-              "å…ƒ]" +
-              i.name;
-            i.children = [];
-          });
-          this.goodsList = res.list;
-          this.initQuery();
+    showUser(data) {
+      let classType = data.type == 1 ? "(带班班级)" : "(观摩班级)";
+      console.log(data);
+      // debugger
+      this.userObj = {
+        classId: data.id,
+        periods_id: data.periods_id,
+        show: true,
+        goods_id: this.goods_id,
+        title: `${data.teacher_name}班级用户列表${classType}`,
+        teacherId: data.teacher_id,
+        class_name: data.class_name,
+        type: data.type,
+        watch_num: this.title.watch_num
+      };
+      console.log(this.userObj);
+    },
+    getTeacher() {
+      if (!this.periods) return;
+      getPeriodsTeacherApi(this.periods.id).then(res => {
+        let obj = {}; //班级老师去重
+        res = res.reduce(function(item, next) {
+          obj[next.teacher_id]
+            ? ""
+            : (obj[next.teacher_id] = true && item.push(next));
+          return item;
+        }, []);
+        this.teacherList = res;
+      });
+    },
+    changePeriods(data) {
+      if (data.length > 1) {
+        this.goods_id = data[0];
+        let nowGoods = this.goodsList.find(i => {
+          return i.id === data[0];
         });
         this.periods = nowGoods.children.find(i => {
           return i.id === data[1];
diff --git a/src/components/logistics/index.vue b/src/components/logistics/index.vue
index 6ff43e93..1a827753 100644
--- a/src/components/logistics/index.vue
+++ b/src/components/logistics/index.vue
@@ -13,35 +13,35 @@
               :value="data.value">
             </el-option>
           </el-select>
-        </el-form-item> -->
+      </el-form-item>-->
       <el-form-item label="期数">
-          <el-cascader
-            :options="goodsList"
-            :props="{value:'id',label:'name'}"
-            @active-item-change="handleItemChange"
-            @change="changePeriods"
-            v-model="selectedGoods"
-          >
-          </el-cascader>
-        </el-form-item>
-        <el-form-item label="主题">
-          <el-select filterable v-model="searchFrom.theme_id" placeholder="请选择"  clearable>
-            <el-option
-              v-for="(data,index) in themeList"
-              :key="index"
-              :label="data.name"
-              :value="data.id">
-            </el-option>
-          </el-select>
-        </el-form-item>
+        <el-cascader
+          :options="goodsList"
+          :props="{value:'id',label:'name'}"
+          @active-item-change="handleItemChange"
+          @change="changePeriods"
+          v-model="selectedGoods"
+        ></el-cascader>
+      </el-form-item>
+      <el-form-item label="主题">
+        <el-select filterable v-model="searchFrom.theme_id" placeholder="请选择" clearable>
+          <el-option
+            v-for="(data,index) in themeList"
+            :key="index"
+            :label="data.name"
+            :value="data.id"
+          ></el-option>
+        </el-select>
+      </el-form-item>
       <!-- <el-form-item label="期数id">
         <el-input v-model="searchFrom.periods_id" style="width: 120px"></el-input>
-      </el-form-item> -->
+      </el-form-item>-->
       <el-form-item>
         <el-button type="primary" plain @click="getList">搜索</el-button>
         <el-button type="success" plain @click="reset">重置</el-button>
         <el-button v-if="!$store.state.readonly" type="primary" plain @click="downLoad()">excel模板下载</el-button>
         <el-button type="primary" plain @click="exportTable" v-if="$store.state.export">导出当前待发货</el-button>
+        <el-button type="primary" plain @click="exportReceiveInfoTable">按期数导出收货信息</el-button>
       </el-form-item>
       <el-form-item v-if="$store.state.export">
         <el-upload
@@ -61,54 +61,63 @@
       <el-tab-pane label="所有已发货" name="2"></el-tab-pane>
     </el-tabs>
     <el-table :data="deliverList" size="mini" style="width: 100%">
-    <el-table-column
-        width="220"
-        className="f-c"
-        label="用户">
+      <el-table-column width="220" class="f-c" label="用户">
         <template slot-scope="scope">
-          <img class="avatar" :src="scope.row.user_avatar"/> {{scope.row.user_nickname}}<br>(ID:{{scope.row.user_id}})<br>手机:{{scope.row.user_mobile}}
+          <img class="avatar" :src="scope.row.user_avatar" />
+          {{scope.row.user_nickname}}
+          <br />
+          (ID:{{scope.row.user_id}})
+          <br />
+          手机:{{scope.row.user_mobile}}
         </template>
       </el-table-column>
       <el-table-column prop="address" label="收货地址">
         <template slot-scope="scope">
-          {{scope.row.receive_name}}<br>
-          {{scope.row.receive_mobile}}<br>
+          {{scope.row.receive_name}}
+          <br />
+          {{scope.row.receive_mobile}}
+          <br />
           {{scope.row.province_name}}{{scope.row.city_name}}{{scope.row.area_name}}{{scope.row.address}}
         </template>
       </el-table-column>
-      <el-table-column prop="periods_title" label="期数名称">
-      </el-table-column>
-      <el-table-column prop="theme_name" label="主题">
-      </el-table-column>
-      <el-table-column prop="deliver_start_at" label="预计发货开始时间">
-      </el-table-column>
-      <el-table-column prop="deliver_end_at" label="预计发货结束时间">
-      </el-table-column>
-      <el-table-column prop="deliver_at" label="发货时间">
-      </el-table-column>
+      <el-table-column prop="periods_title" label="期数名称"></el-table-column>
+      <el-table-column prop="theme_name" label="主题"></el-table-column>
+      <el-table-column prop="deliver_start_at" label="预计发货开始时间"></el-table-column>
+      <el-table-column prop="deliver_end_at" label="预计发货结束时间"></el-table-column>
+      <el-table-column prop="deliver_at" label="发货时间"></el-table-column>
       <el-table-column prop="status" label="物流状态">
         <template slot-scope="scope">
-          {{scope.row.status|LogisticsStatusFil}}<br>
-          <span v-if="searchFrom.type==2">名称:{{scope.row.express_name}}<br>单号:{{scope.row.express_no}}</span>
+          {{scope.row.status|LogisticsStatusFil}}
+          <br />
+          <span v-if="searchFrom.type==2">
+            名称:{{scope.row.express_name}}
+            <br />
+            单号:{{scope.row.express_no}}
+          </span>
         </template>
       </el-table-column>
       <el-table-column width="150" label="操作" v-if="!$store.state.readonly" fixed="right">
         <template slot-scope="scope">
-          <el-button  @click="editAddress(scope.row)"  plain type="info" size="mini">
-                编辑收货地址
-              </el-button>
+          <el-button @click="editAddress(scope.row)" plain type="info" size="mini">编辑收货地址</el-button>
         </template>
       </el-table-column>
     </el-table>
     <page :nowPage="nowPage" :total="total" @pageChange="onPageChange" @sizeChange="onSizeChange" />
     <address-dialog :dialogObj="dialogObj" @reflash="onUpdateAddress"></address-dialog>
+    <receiveInfoDialog
+      :goodsList="goodsList"
+      :showFlag="showFlag"
+      :cancelEvent="cancelEvent"
+      :sureEvent="sureEvent"
+    />
   </div>
 </template>
 
 <script>
 import page from "../framework/page";
-import md5 from 'js-md5';
+import md5 from "js-md5";
 import addressDialog from "./dialog";
+import receiveInfoDialog from "./receiveInfoDialog";
 import {
   getDeliverListApi,
   getPeriodsApi,
@@ -117,16 +126,14 @@ import {
   exportExcelApi,
   getThemeListApi
 } from "../../service/api";
-import {
-  LogisticsStatus,
-  GOODSTYPE 
-} from "../../util/wordbook";
+import { LogisticsStatus, GOODSTYPE } from "../../util/wordbook";
 
 export default {
   name: "index",
   components: {
     page,
-    addressDialog
+    addressDialog,
+    receiveInfoDialog
   },
   data() {
     let singjson = {
@@ -136,47 +143,61 @@ export default {
       dialogObj: {
         show: false
       },
-      adressDialog:false,
+      showFlag: false,
+      adressDialog: false,
       searchFrom: {
         user_id: "",
         theme_id: "",
-        periods_id:"",
-        type:""
+        periods_id: "",
+        type: ""
       },
       nowPage: 1,
       total: 0,
       limit: 10,
-      deliverList:[],
+      deliverList: [],
       selectedGoods: [],
-      secGoods:[],
-      periodsId:null,
-      goods_id:null,
-      goodsList:[],
-      themeList:[],
-      param_token:md5(JSON.stringify(singjson)),
-      uploadHeader:{token:localStorage.getItem('cc_token')},
-      logisticsType:[{value:'0',name:'当前待发货 '},{value:'1',name:'所有待发货 '},{value:'2',name:'所有已发货 '}]
+      secGoods: [],
+      periodsId: null,
+      goods_id: null,
+      goodsList: [],
+      themeList: [],
+      param_token: md5(JSON.stringify(singjson)),
+      uploadHeader: { token: localStorage.getItem("cc_token") },
+      logisticsType: [
+        { value: "0", name: "当前待发货 " },
+        { value: "1", name: "所有待发货 " },
+        { value: "2", name: "所有已发货 " }
+      ]
     };
   },
   filters: {
-    LogisticsStatusFil(val){
-     return LogisticsStatus[val]
+    LogisticsStatusFil(val) {
+      return LogisticsStatus[val];
     }
   },
   mounted() {
-    this.init()
+    this.init();
   },
   methods: {
-    downLoad(){
-      window.open('/static/待发货模板.xls')
+    cancelEvent() {
+      this.showFlag = false;
+    },
+    sureEvent() {
+      this.showFlag = false;
+    },
+    exportReceiveInfoTable() {
+      this.showFlag = true;
+    },
+    downLoad() {
+      window.open("/static/待发货模板.xls");
     },
     handleClick(tab) {
-          this.searchFrom.type = tab.name;
-          this.getList();
-        },
+      this.searchFrom.type = tab.name;
+      this.getList();
+    },
     editAddress(row) {
       // this.dialogObj={show:true}
-      console.log(row)
+      console.log(row);
       // if (!row || !row.province_name) {
       //   this.dialogObj.province = "";
       //   this.dialogObj.city = "";
@@ -188,150 +209,191 @@ export default {
       // }
       this.dialogObj.detail = row.address;
       this.dialogObj.receive_mobile = row.receive_mobile;
-      this.dialogObj.receive_name =row.receive_name;
-      this.dialogObj.province_name = '';
+      this.dialogObj.receive_name = row.receive_name;
+      this.dialogObj.province_name = "";
       this.dialogObj.city_name = "";
-      this.dialogObj.district_name ='';
+      this.dialogObj.district_name = "";
       this.dialogObj.id = row.id;
       this.dialogObj.show = true;
     },
     onUpdateAddress() {
       this.dialogObj.show = false;
-      this.getList()
+      this.getList();
     },
-    fileSuccess(){
+    fileSuccess() {
       this.$message({
-        message: '提交成功,请稍后刷新',
-        type: 'success'
+        message: "提交成功,请稍后刷新",
+        type: "success"
       });
-      this.getList()
+      this.getList();
     },
-    init(){
-      this.getList()
+    init() {
+      this.getList();
       let json = {
-          page: 1,
-          limit: 100,
-          goods_type:'1,2'
-        };
-        getThemeListApi({page: 1,limit: 100}).then(res=>{
-          this.themeList = res.list
-        })
-        getGoodsListApi(json).then(res=>{
-          console.log(res)
-          res.list.forEach(i=>{
-            i.name = '['+i.id+']'+'[' + GOODSTYPE[i.goods_type] + ']' + '[' +i.current_price / 100 + 'å…ƒ]' + i.name
-            i.children = [];
-          });
-          this.goodsList = res.list;
-          // this.initQuery();
+        page: 1,
+        limit: 100,
+        goods_type: "1,2"
+      };
+      getThemeListApi({ page: 1, limit: 100 }).then(res => {
+        this.themeList = res.list;
+      });
+      getGoodsListApi(json).then(res => {
+        console.log(res);
+        res.list.forEach(i => {
+          i.name =
+            "[" +
+            i.id +
+            "]" +
+            "[" +
+            GOODSTYPE[i.goods_type] +
+            "]" +
+            "[" +
+            i.current_price / 100 +
+            "å…ƒ]" +
+            i.name;
+          i.children = [];
         });
+        this.goodsList = res.list;
+        // this.initQuery();
+      });
     },
-    exportTable(){
-        let json = {};
-        if (this.searchFrom.user_id) {
-          json.user_id = this.searchFrom.user_id
-        }
-        if (this.searchFrom.theme_id) {
-          json.theme_id = this.searchFrom.theme_id
-        }
-        if (this.searchFrom.periods_id) {
-          json.periods_id = this.searchFrom.periods_id
-        }
-        exportExcelApi('/api/admin/order/deliver/list/export',json)
-      },
-    initQuery(){
-        let _query = this.$route.query;
-        if (_query && _query.goods_id && _query.periods_id) { 
-          this.goods_id = _query.goods_id;
-          this.selectedGoods = [parseInt(_query.goods_id),parseInt(_query.periods_id)];
-          getPeriodsApi({goods_id:this.selectedGoods[0],limit:100}).then(res=>{
-            res.list.forEach(i=>{i.name = i.title});
-            this.goodsList.find(i=>{return i.id === this.selectedGoods[0]}).children = res.list
-            let nowGoods = this.goodsList.find(i=>{return i.id === this.selectedGoods[0]});
-            this.periods = nowGoods.children.find(i=>{return i.id === this.selectedGoods[1]});
-            console.log(this.periods)
-          })
-        } else {
-          getDefaultPeriodsApi().then(res=>{
-            console.log(res)
-            // 
-            if(res){
-              this.goods_id = res.goods_id;
-              this.selectedGoods = [parseInt(res.goods_id),parseInt(res.id)];
-              getPeriodsApi({goods_id:this.selectedGoods[0],limit:100}).then(res=>{
-                res.list.forEach(i=>{i.name = i.title});
-                this.goodsList.find(i=>{return i.id === this.selectedGoods[0]}).children = res.list
-                let nowGoods = this.goodsList.find(i=>{return i.id === this.selectedGoods[0]});
-                this.periods = nowGoods.children.find(i=>{return i.id === this.selectedGoods[1]});
-                this.teacher_id = '';
-                console.log(this.periods)
+    exportTable() {
+      let json = {};
+      if (this.searchFrom.user_id) {
+        json.user_id = this.searchFrom.user_id;
+      }
+      if (this.searchFrom.theme_id) {
+        json.theme_id = this.searchFrom.theme_id;
+      }
+      if (this.searchFrom.periods_id) {
+        json.periods_id = this.searchFrom.periods_id;
+      }
+      exportExcelApi("/api/admin/order/deliver/list/export", json);
+    },
+    initQuery() {
+      let _query = this.$route.query;
+      if (_query && _query.goods_id && _query.periods_id) {
+        this.goods_id = _query.goods_id;
+        this.selectedGoods = [
+          parseInt(_query.goods_id),
+          parseInt(_query.periods_id)
+        ];
+        getPeriodsApi({ goods_id: this.selectedGoods[0], limit: 100 }).then(
+          res => {
+            res.list.forEach(i => {
+              i.name = i.title;
+            });
+            this.goodsList.find(i => {
+              return i.id === this.selectedGoods[0];
+            }).children = res.list;
+            let nowGoods = this.goodsList.find(i => {
+              return i.id === this.selectedGoods[0];
+            });
+            this.periods = nowGoods.children.find(i => {
+              return i.id === this.selectedGoods[1];
+            });
+            console.log(this.periods);
+          }
+        );
+      } else {
+        getDefaultPeriodsApi().then(res => {
+          console.log(res);
+          //
+          if (res) {
+            this.goods_id = res.goods_id;
+            this.selectedGoods = [parseInt(res.goods_id), parseInt(res.id)];
+            getPeriodsApi({ goods_id: this.selectedGoods[0], limit: 100 }).then(
+              res => {
+                res.list.forEach(i => {
+                  i.name = i.title;
+                });
+                this.goodsList.find(i => {
+                  return i.id === this.selectedGoods[0];
+                }).children = res.list;
+                let nowGoods = this.goodsList.find(i => {
+                  return i.id === this.selectedGoods[0];
+                });
+                this.periods = nowGoods.children.find(i => {
+                  return i.id === this.selectedGoods[1];
+                });
+                this.teacher_id = "";
+                console.log(this.periods);
                 // this.getClassList()
-              });
-            }
-          })
-        }
-        console.log(this.goodsList)
-      },
-    onPageChange(val){
+              }
+            );
+          }
+        });
+      }
+      console.log(this.goodsList);
+    },
+    onPageChange(val) {
       // console.log(val)
-        this.nowPage = val;
-        this.getList()
-      },
-      onSizeChange(val){
-        this.limit = val;
-        this.nowPage = 1;
-        this.getList()
-      },
-      getList(){
-        let json = {
+      this.nowPage = val;
+      this.getList();
+    },
+    onSizeChange(val) {
+      this.limit = val;
+      this.nowPage = 1;
+      this.getList();
+    },
+    getList() {
+      let json = {
         limit: this.limit,
         page: this.nowPage
-        };
-        if(this.searchFrom.user_id){
-        json.user_id = this.searchFrom.user_id
-        }
-        if(this.searchFrom.theme_id){
-        json.theme_id = this.searchFrom.theme_id
-        }
-        if(this.searchFrom.periods_id){
-        json.periods_id = this.searchFrom.periods_id
-        }
-        if(this.searchFrom.type){
-        json.type = this.searchFrom.type
-        }
-        
-        getDeliverListApi(json).then((res)=>{
-          this.deliverList = res.list
-          this.total = res.total
-          console.log(this.deliverList)
-        })
-      },
-      reset(){
-          this.searchFrom= {
-          user_id: "",
-          theme_id: "",
-          periods_id:"",
-          type:''
-        }
-        this.getList()
-      },
-      changePeriods(data){
-        if(data.length>1){
-          this.goods_id = data[0];
-          let nowGoods = this.goodsList.find(i=>{return i.id === data[0]});
-          this.periods = nowGoods.children.find(i=>{return i.id === data[1]});
-          console.log(this.goodsList)
-          console.log(this.periods)
-          this.searchFrom.periods_id = this.periods.id
-          // debugger
-        }
-      },
-      handleItemChange(val){
-        getPeriodsApi({goods_id:val[0],limit:100}).then(res=>{
-          res.list.forEach(i=>{i.name = i.title});
-          this.goodsList.find(i=>{return i.id === val[0]}).children = res.list
-        })
-      },
+      };
+      if (this.searchFrom.user_id) {
+        json.user_id = this.searchFrom.user_id;
+      }
+      if (this.searchFrom.theme_id) {
+        json.theme_id = this.searchFrom.theme_id;
+      }
+      if (this.searchFrom.periods_id) {
+        json.periods_id = this.searchFrom.periods_id;
+      }
+      if (this.searchFrom.type) {
+        json.type = this.searchFrom.type;
+      }
+
+      getDeliverListApi(json).then(res => {
+        this.deliverList = res.list;
+        this.total = res.total;
+        console.log(this.deliverList);
+      });
+    },
+    reset() {
+      this.searchFrom = {
+        user_id: "",
+        theme_id: "",
+        periods_id: "",
+        type: ""
+      };
+      this.getList();
+    },
+    changePeriods(data) {
+      if (data.length > 1) {
+        this.goods_id = data[0];
+        let nowGoods = this.goodsList.find(i => {
+          return i.id === data[0];
+        });
+        this.periods = nowGoods.children.find(i => {
+          return i.id === data[1];
+        });
+        console.log(this.goodsList);
+        console.log(this.periods);
+        this.searchFrom.periods_id = this.periods.id;
+        // debugger
+      }
+    },
+    handleItemChange(val) {
+      getPeriodsApi({ goods_id: val[0], limit: 100 }).then(res => {
+        res.list.forEach(i => {
+          i.name = i.title;
+        });
+        this.goodsList.find(i => {
+          return i.id === val[0];
+        }).children = res.list;
+      });
+    }
   }
 };
 </script>
@@ -340,7 +402,7 @@ export default {
 .sms {
   padding: 20px 0;
 }
-.el-button+.el-button{
+.el-button + .el-button {
   margin-left: 0;
   /* margin-top: 10px; */
 }
diff --git a/src/components/logistics/receiveInfoDialog.vue b/src/components/logistics/receiveInfoDialog.vue
new file mode 100644
index 00000000..6a28c1d0
--- /dev/null
+++ b/src/components/logistics/receiveInfoDialog.vue
@@ -0,0 +1,70 @@
+<template>
+  <el-dialog :visible.sync="showFlag" width="800px" center title="按期数导出收货信息">
+    <el-form label-width="150px">
+      <el-form-item label="期数">
+        <el-cascader
+          :options="goodsList"
+          :props="{value:'id',label:'name'}"
+          @active-item-change="handleItemChange"
+          @change="changePeriods"
+          v-model="selectedGoods"
+        ></el-cascader>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="cancelClick">取 消</el-button>
+      <el-button type="primary" @click="onAdd">确 定</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+import { getPeriodsApi, exportReceiveInfoApi } from "../../service/api";
+export default {
+  name: "receiveInfoDialog",
+  props: ["showFlag", "goodsList", "cancelEvent", "sureEvent"],
+  data() {
+    return {};
+  },
+  methods: {
+    cancelClick() {
+      this.cancelEvent();
+    },
+    onAdd() {
+      if (this.periods && this.periods.id) {
+        this.exportReceiveInfo().then(() => {
+          this.sureEvent();
+        });
+      } else {
+        Vue.prototype.$msgbox({
+          message: "请选择期数",
+          type: "warning"
+        });
+      }
+    },
+    exportReceiveInfo() {
+      return exportReceiveInfoApi(this.periods.id);
+    },
+    changePeriods(data) {
+      if (data.length > 1) {
+        this.goods_id = data[0];
+        let nowGoods = this.goodsList.find(i => {
+          return i.id === data[0];
+        });
+        this.periods = nowGoods.children.find(i => {
+          return i.id === data[1];
+        });
+      }
+    },
+    handleItemChange(val) {
+      getPeriodsApi({ goods_id: val[0], limit: 100 }).then(res => {
+        res.list.forEach(i => {
+          i.name = i.title;
+        });
+        this.goodsList.find(i => {
+          return i.id === val[0];
+        }).children = res.list;
+      });
+    }
+  }
+};
+</script>
\ No newline at end of file
diff --git a/src/components/marketStatistics/index.vue b/src/components/marketStatistics/index.vue
index af22e6d4..0432f685 100644
--- a/src/components/marketStatistics/index.vue
+++ b/src/components/marketStatistics/index.vue
@@ -8,91 +8,49 @@
       height="calc(100vh - 60px)"
       size="mini"
       :row-class-name="tableRowClassName"
-      :span-method="arraySpanMethod">
-      <el-table-column
-        min-width="180"
-        prop="wait_join_num"
-        align="left"
-        fixed="left"
-        label="期数总状况">
+      :span-method="arraySpanMethod"
+    >
+      <el-table-column min-width="180" prop="wait_join_num" align="left" fixed="left" label="期数总状况">
         <template slot-scope="scope">
           期数名称:{{scope.row.title}}
-          <br>
+          <br />
           开始时间:{{scope.row.start_at}}
-          <br>
+          <br />
           团购待进班人数:{{scope.row.wait_join_num}}
-          <br>
+          <br />
           外部订单待进班人数:{{scope.row.other_wait_join_num}}
-          <br>
+          <br />
           总进班人数:{{scope.row.total_join_num}}
-          <br>
+          <br />
           需求供量:{{scope.row.total_max_join_num}}
-          <br>
-          目标差距:{{scope.row.target_diff < 0 ? '超标'+scope.row.target_diff * -1  :scope.row.target_diff}}个
-          <br>
-          完成率:<el-progress
-          style="display: inline-block;width: calc(90% - 50px)" :text-inside="true" :stroke-width="16" :status="scope.row.complete_rate>=1?'exception':'success'" :percentage="scope.row.complete_rate*1000/10"></el-progress>
+          <br />
+          目标差距:{{scope.row.target_diff < 0 ? '超标'+scope.row.target_diff * -1 :scope.row.target_diff}}个
+          <br />完成率:
+          <el-progress
+            style="display: inline-block;width: calc(90% - 50px)"
+            :text-inside="true"
+            :stroke-width="16"
+            :status="scope.row.complete_rate>=1?'exception':'success'"
+            :percentage="scope.row.complete_rate*1000/10"
+          ></el-progress>
         </template>
         <!-- exception -->
       </el-table-column>
-      <el-table-column
-        prop="class_name"
-        align="center"
-        min-width="80"
-        fixed="left"
-        label="班级名称">
-        <template slot-scope="scope">
-          {{scope.row.title === '合计'?'合计':scope.row.class_name}}
-        </template>
-      </el-table-column>
-      <el-table-column
-        prop="max_join_num"
-        min-width="60"
-        align="center"
-        label="预计加入人数">
-      </el-table-column>
-      <el-table-column
-        prop="join_num"
-        min-width="60"
-        align="center"
-        label="已进班人数">
+      <el-table-column prop="class_name" align="center" min-width="80" fixed="left" label="班级名称">
+        <template slot-scope="scope">{{scope.row.title === '合计'?'合计':scope.row.class_name}}</template>
       </el-table-column>
-      <el-table-column
-        prop="other_allot_num"
-        align="center"
-        min-width="60"
-        label="外部订单已分配人数">
-      </el-table-column>
-      <el-table-column
-        v-for="(data,index) in dateList"
-        align="center"
-        :key="index"
-        :label="data">
-        <el-table-column
-          align="center"
-          min-width="60px"
-          prop="wait_join_num"
-          label="系统招生量">
-          <template slot-scope="scope">
-            {{scope.row.date[index].total_buy_num}}
-          </template>
+      <el-table-column prop="max_join_num" min-width="60" align="center" label="预计加入人数"></el-table-column>
+      <el-table-column prop="join_num" min-width="60" align="center" label="已进班人数"></el-table-column>
+      <el-table-column prop="other_allot_num" align="center" min-width="60" label="外部订单已分配人数"></el-table-column>
+      <el-table-column v-for="(data,index) in dateList" align="center" :key="index" :label="data">
+        <el-table-column align="center" min-width="60px" prop="wait_join_num" label="系统招生量">
+          <template slot-scope="scope">{{scope.row.date[index].total_buy_num}}</template>
         </el-table-column>
-        <el-table-column
-          align="center"
-          min-width="60px"
-          prop="wait_join_num"
-          label="外部订单招生量">
-          <template slot-scope="scope">
-            {{scope.row.date[index].total_other_buy_num}}
-          </template>
+        <el-table-column align="center" min-width="60px" prop="wait_join_num" label="外部订单招生量">
+          <template slot-scope="scope">{{scope.row.date[index].total_other_buy_num}}</template>
         </el-table-column>
-        <el-table-column
-          align="center"
-          min-width="60px"
-          label="进班量">
-          <template slot-scope="scope">
-            {{scope.row.date[index].total_into_num}}
-          </template>
+        <el-table-column align="center" min-width="60px" label="进班量">
+          <template slot-scope="scope">{{scope.row.date[index].total_into_num}}</template>
         </el-table-column>
       </el-table-column>
     </el-table>
@@ -100,78 +58,92 @@
 </template>
 
 <script>
-  import {getPeriodsClassCurDataApi} from "../../service/api";
-  export default {
-    name: "index",
-    data(){
-      return {
-        list:[],
-        dateList:[],
-        propertyList:["title","start_at","total_join_num","total_max_join_num","total_target_join_num","complete_rate","target_diff",'wait_join_num','other_wait_join_num'],
+import { getPeriodsClassCurDataApi } from "../../service/api";
+export default {
+  name: "index",
+  data() {
+    return {
+      list: [],
+      dateList: [],
+      propertyList: [
+        "title",
+        "start_at",
+        "total_join_num",
+        "total_max_join_num",
+        "total_target_join_num",
+        "complete_rate",
+        "target_diff",
+        "wait_join_num",
+        "other_wait_join_num"
+      ]
+    };
+  },
+  methods: {
+    initPage() {
+      getPeriodsClassCurDataApi().then(res => {
+        this.list = res;
+        if (res[0].date) {
+          res[0].date.forEach(i => {
+            this.dateList.push(i.pay_date);
+          });
+        }
+      });
+    },
+    tableRowClassName({ row, rowIndex }) {
+      if (rowIndex === 0) {
+        return "warning-row";
       }
+      return "";
     },
-    methods:{
-      initPage(){
-        getPeriodsClassCurDataApi().then(res=>{
-          this.list = res;
-          if(res[0].date){
-            res[0].date.forEach(i=>{
-              this.dateList.push(i.pay_date)
-            })
-          }
-        })
-      },
-      tableRowClassName({row, rowIndex}) {
-        if (rowIndex === 0) {
-          return 'warning-row';
-        }
-        return '';
-      },
-      arraySpanMethod(data){
-        if(this.propertyList.indexOf(data.column.property) > -1 ){
-          if(data.rowIndex === 0 || data.row.id !== this.list[data.rowIndex-1].id){
-            let rowspan = 1;
-            for (let i = data.rowIndex + 1; i < this.list.length ; i ++){
-              if(data.row.id === this.list[i].id){
-                rowspan ++
-              }else{
-                break;
-              }
+    arraySpanMethod(data) {
+      if (this.propertyList.indexOf(data.column.property) > -1) {
+        if (
+          data.rowIndex === 0 ||
+          data.row.id !== this.list[data.rowIndex - 1].id
+        ) {
+          let rowspan = 1;
+          for (let i = data.rowIndex + 1; i < this.list.length; i++) {
+            if (data.row.id === this.list[i].id) {
+              rowspan++;
+            } else {
+              break;
             }
-            return {
-              rowspan: rowspan,
-              colspan: 1
-            };
-          }else{
-            return {
-              rowspan: 0,
-              colspan: 0
-            };
           }
-        }else{
           return {
-            rowspan: 1,
+            rowspan: rowspan,
             colspan: 1
           };
+        } else {
+          return {
+            rowspan: 0,
+            colspan: 0
+          };
         }
+      } else {
+        return {
+          rowspan: 1,
+          colspan: 1
+        };
       }
-    },
-    created() {
-      this.initPage()
     }
+  },
+  created() {
+    this.initPage();
   }
+};
 </script>
 
 <style scoped lang="less">
-  /deep/.el-table--enable-row-hover .el-table__body tr:hover>td {
-    background-color: #fff;
-  }
-  /deep/ .el-table .warning-row {
-    background: oldlace;
-  }
-  /deep/.el-progress-bar__inner{
-    max-width: 100% !important;
-  }
-  .el-main .content .router-block .child-view{height: 100vh;}
-
+/deep/.el-table--enable-row-hover .el-table__body tr:hover > td {
+  background-color: #fff;
+}
+/deep/ .el-table .warning-row {
+  background: oldlace;
+}
+/deep/.el-progress-bar__inner {
+  max-width: 100% !important;
+}
+.el-main .content .router-block .child-view {
+  height: 100vh;
+}
 </style>
diff --git a/src/service/api.js b/src/service/api.js
index 94903453..ed66ccfd 100644
--- a/src/service/api.js
+++ b/src/service/api.js
@@ -1179,4 +1179,17 @@ const getchannelTransListUrl = `${_baseUrl}api/admin/channel/conversion/list`;
 export const getchannelTransListApi = function (json) {
     return Vue.prototype.$fetch(getchannelTransListUrl, json)
 };
+//按期数导出收货信息
+const exportReceiveInfoUrl = `${_baseUrl}api/admin/order/deliver/periods/export/`;
+export const exportReceiveInfoApi = function (periods_id) {
+    let url = `${exportReceiveInfoUrl}${periods_id}`;
+    window.open(url);
+    return new Promise((resolve, reject) => {
+        resolve();
+    })
+
+};
+
+ 
+
 // /api/admin/student/deliver/record/list
\ No newline at end of file
diff --git a/src/util/menuList.js b/src/util/menuList.js
index acc31ca3..2116266f 100644
--- a/src/util/menuList.js
+++ b/src/util/menuList.js
@@ -321,6 +321,24 @@ export default [{
     }
   ]
 },
+{
+  name: '',
+  value: '数据管理',
+  icon: 'icon-shezhi',
+  list: [
+    {
+      value: '渠道转化列表',
+      routerName: 'channelTransList',
+      path: '/channelTransList',
+      cover: '9-1',
+      router: {
+        path: '/channelTransList',
+        name: 'channelTransList',
+        component: e => require(['@/components/channelTransList'], e),
+      }
+    }
+  ]
+},
 {
   name: '',
   value: '实物管理',
@@ -541,24 +559,7 @@ export default [{
   },
   ]
 },
-{
-  name: '',
-  value: '数据管理',
-  icon: 'icon-shezhi',
-  list: [
-    {
-      value: '渠道转化列表',
-      routerName: 'channelTransList',
-      path: '/channelTransList',
-      cover: '9-1',
-      router: {
-        path: '/channelTransList',
-        name: 'channelTransList',
-        component: e => require(['@/components/channelTransList'], e),
-      }
-    }
-  ]
-},
+
 {
   name: '',
   value: '后台管理',
-- 
2.21.0