Browse Source

Merge branch 'V1.1.5' of http://git.tjyourong.com.cn/ctop/adsp-vue into V1.1.5

魏志佳 4 years ago
parent
commit
caf572be22

+ 75 - 70
src/components/ChartCard.vue

@@ -7,7 +7,12 @@
           <slot name="action"></slot>
         </span>
       </div>
-      <div class="total"><span>{{ total }}</span></div>
+      <div class="total" style="display: flex; justify-content: space-between">
+        <span>{{ total }}</span>
+        <span>
+          <slot name="percentage"></slot>
+        </span>
+      </div>
     </div>
     <div class="chart-card-content">
       <div class="content-fix">
@@ -23,89 +28,89 @@
 </template>
 
 <script>
-  export default {
-    name: "ChartCard",
-    props: {
-      title: {
-        type: String,
-        default: ''
-      },
-      total: {
-        type: String,
-        default: ''
-      },
-      loading: {
-        type: Boolean,
-        default: false
-      }
-    }
-  }
+export default {
+  name: 'ChartCard',
+  props: {
+    title: {
+      type: String,
+      default: '',
+    },
+    total: {
+      type: String,
+      default: '',
+    },
+    loading: {
+      type: Boolean,
+      default: false,
+    },
+  },
+}
 </script>
 
 <style lang="scss" scoped>
-  .chart-card-header {
+.chart-card-header {
+  position: relative;
+  overflow: hidden;
+  width: 100%;
+
+  .meta {
     position: relative;
     overflow: hidden;
     width: 100%;
-
-    .meta {
-      position: relative;
-      overflow: hidden;
-      width: 100%;
-      color: rgba(0, 0, 0, .45);
-      font-size: 14px;
-      line-height: 22px;
-    }
+    color: rgba(0, 0, 0, 0.45);
+    font-size: 14px;
+    line-height: 22px;
   }
+}
 
-  .chart-card-action {
-    cursor: pointer;
-    position: absolute;
-    top: 0;
-    right: 0;
-  }
-
-  .chart-card-footer {
-    border-top: 1px solid #e8e8e8;
-    padding-top: 9px;
-    margin-top: 8px;
+.chart-card-action {
+  cursor: pointer;
+  position: absolute;
+  top: 0;
+  right: 0;
+}
 
-    > * {
-      position: relative;
-    }
-
-    .field {
-      white-space: nowrap;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      margin: 0;
-    }
-  }
+.chart-card-footer {
+  border-top: 1px solid #e8e8e8;
+  padding-top: 9px;
+  margin-top: 8px;
 
-  .chart-card-content {
-    margin-bottom: 12px;
+  > * {
     position: relative;
-    height: 46px;
-    width: 100%;
-
-    .content-fix {
-      position: absolute;
-      left: 0;
-      bottom: 0;
-      width: 100%;
-    }
   }
 
-  .total {
+  .field {
+    white-space: nowrap;
     overflow: hidden;
     text-overflow: ellipsis;
-    word-break: break-all;
-    white-space: nowrap;
-    color: #000;
-    margin-top: 4px;
-    margin-bottom: 0;
-    font-size: 30px;
-    line-height: 38px;
-    height: 38px;
+    margin: 0;
+  }
+}
+
+.chart-card-content {
+  margin-bottom: 12px;
+  position: relative;
+  height: 46px;
+  width: 100%;
+
+  .content-fix {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 100%;
   }
+}
+
+.total {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  word-break: break-all;
+  white-space: nowrap;
+  color: #000;
+  margin-top: 4px;
+  margin-bottom: 0;
+  font-size: 30px;
+  line-height: 38px;
+  height: 38px;
+}
 </style>

BIN
src/views/modules/Statistics/materialReport/image/1.png


BIN
src/views/modules/Statistics/materialReport/image/2.png


BIN
src/views/modules/Statistics/materialReport/image/3.png


BIN
src/views/modules/Statistics/materialReport/image/4.png


BIN
src/views/modules/Statistics/materialReport/image/5.png


+ 498 - 0
src/views/modules/Statistics/materialReport/marterialDetail.vue

@@ -0,0 +1,498 @@
+<style lang="scss" scoped>
+#office-iframe {
+  height: 800px;
+}
+</style>
+<style>
+.info-detail .ant-descriptions-item-content {
+  font-weight: bold;
+}
+.info-detail .ant-descriptions-item-label {
+  color: darkgray;
+  min-width: 80px;
+}
+.info-detail table tr td {
+  border: 0;
+}
+.show-data span {
+  display: inline-block;
+  width: 85px;
+}
+</style>
+<template>
+  <a-row :gutter="10">
+    <a-spin :spinning="spinning">
+      <a-col :sm="6" style="margin-bottom: 20px; z-index: 10">
+        <a-card class="search-box" style="min-height: 500px" v-if="materialInfo">
+          <video class="video" :src="materialInfo.url" controls="controls" style="width: 100%">
+            您的浏览器不支持 video 标签。
+          </video>
+        </a-card>
+      </a-col>
+      <a-col :sm="18" style="margin-bottom: 20px; z-index: 10">
+        <a-card class="search-box info-detail" style="min-height: 300px" v-if="materialInfo">
+          <a-descriptions title="视频信息">
+            <a-descriptions-item label="素材标题" :span="3"> {{ materialInfo.materialName }} </a-descriptions-item>
+            <a-descriptions-item label="素材ID"> {{ materialInfo.materialId }} </a-descriptions-item>
+            <a-descriptions-item label="上线时间"> {{ materialInfo.createTime.split(' ')[0] }} </a-descriptions-item>
+            <a-descriptions-item label="素材类型">
+              {{ materialInfo.materialType == '' ? '无' : materialInfo.materialType }}
+            </a-descriptions-item>
+            <a-descriptions-item label="视频时长"> {{ materialInfo.second }}s </a-descriptions-item>
+            <a-descriptions-item label="视频大小">
+              {{ materialInfo.size }}
+            </a-descriptions-item>
+            <a-descriptions-item label="视频尺寸">
+              {{ materialInfo.width }}*{{ materialInfo.height }}
+            </a-descriptions-item>
+            <a-descriptions-item label="投放媒体">
+              {{ materialInfo.madia }}
+            </a-descriptions-item>
+            <a-descriptions-item label="素材渠道">
+              {{ materialInfo.channelType }}
+            </a-descriptions-item>
+            <a-descriptions-item label="供应商">
+              {{ materialInfo.supplier }}
+            </a-descriptions-item>
+            <a-descriptions-item label="关联项目">
+              {{ materialInfo.projectName }}
+            </a-descriptions-item>
+            <a-descriptions-item label="唯一编码" :span="2">
+              {{ materialInfo.code }}
+            </a-descriptions-item>
+
+            <a-descriptions-item label="设计组长" :span="3" style="margin-top: 10px">
+              {{ materialInfo.leaderName }}
+            </a-descriptions-item>
+            <a-descriptions-item label="编导">
+              {{ materialInfo.planName == '' ? '无' : materialInfo.planName }}
+            </a-descriptions-item>
+            <a-descriptions-item label="拍摄">
+              {{ materialInfo.shotName == '' ? '无' : materialInfo.shotName }}
+            </a-descriptions-item>
+            <a-descriptions-item label="剪辑">
+              {{ materialInfo.clipName == '' ? '无' : materialInfo.clipName }}
+            </a-descriptions-item>
+          </a-descriptions>
+        </a-card>
+        <a-card
+          class="search-box"
+          style="min-height: 300px; margin: 20px 0"
+          title="数据概览"
+          v-if="dataView && $route.query.mediaId == 2"
+        >
+          <a-row :gutter="15">
+            <a-col :xl="6" class="show-data">
+              <h3>素材消耗</h3>
+              <p
+                :style="{ color: dataView.charge[0].charge > dataView.charge[2].charge ? '#F66C6D' : '#67C239' }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.charge[0].charge | decimalsHandle }}
+              </p>
+              <p><span>项目top</span>{{ dataView.charge[1].charge | decimalsHandle }}</p>
+              <p><span>数据库均值</span>{{ dataView.charge[2].charge | decimalsHandle }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>封面曝光数</h3>
+              <p
+                :style="{
+                  color: dataView.photoShow[0].photoShow > dataView.photoShow[2].photoShow ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.photoShow[0].photoShow }}
+              </p>
+              <p><span>项目top</span>{{ dataView.photoShow[1].photoShow }}</p>
+              <p><span>数据库均值</span>{{ dataView.photoShow[2].photoShow }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>封面点击数</h3>
+              <p
+                :style="{
+                  color: dataView.photoClick[0].photoClick > dataView.photoClick[2].photoClick ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.photoClick[0].photoClick }}
+              </p>
+              <p><span>项目top</span>{{ dataView.photoClick[1].photoClick }}</p>
+              <p><span>数据库均值</span>{{ dataView.photoClick[2].photoClick }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>素材曝光数</h3>
+              <p
+                :style="{ color: dataView.aclick[0].aclick > dataView.aclick[2].aclick ? '#F66C6D' : '#67C239' }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.aclick[0].aclick }}
+              </p>
+              <p><span>项目top</span>{{ dataView.aclick[1].aclick }}</p>
+              <p><span>数据库均值</span>{{ dataView.aclick[2].aclick }}</p>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15" style="margin-top: 20px">
+            <a-col :xl="6" class="show-data">
+              <h3>行为数</h3>
+              <p
+                :style="{ color: dataView.bclick[0].bclick > dataView.bclick[2].bclick ? '#F66C6D' : '#67C239' }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.bclick[0].bclick }}
+              </p>
+              <p><span>项目top</span>{{ dataView.bclick[1].bclick }}</p>
+              <p><span>数据库均值</span>{{ dataView.bclick[2].bclick }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>激活数</h3>
+              <p
+                :style="{
+                  color: dataView.activation[0].activation > dataView.activation[2].activation ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.activation[0].activation }}
+              </p>
+              <p><span>项目top</span>{{ dataView.activation[1].activation }}</p>
+              <p><span>数据库均值</span>{{ dataView.activation[2].activation }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>3s播放率</h3>
+              <p
+                :style="{
+                  color: dataView.play3sRate[0].play3sRate > dataView.play3sRate[2].play3sRate ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ (dataView.play3sRate[0].play3sRate * 100).toFixed(2) + '%' }}
+              </p>
+              <p><span>项目top</span>{{ (dataView.play3sRate[1].play3sRate * 100).toFixed(2) + '%' }}</p>
+              <p><span>数据库均值</span>{{ (dataView.play3sRate[2].play3sRate * 100).toFixed(2) + '%' }}</p>
+            </a-col>
+          </a-row>
+        </a-card>
+        <a-card
+          class="search-box"
+          style="min-height: 300px; margin: 20px 0"
+          title="数据概览"
+          v-if="dataView && $route.query.mediaId == 1"
+        >
+          <a-row :gutter="15">
+            <a-col :xl="6" class="show-data">
+              <h3>素材消耗</h3>
+              <p
+                :style="{ color: dataView.cost[0].cost > dataView.cost[2].cost ? '#F66C6D' : '#67C239' }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.cost[0].cost | decimalsHandle }}
+              </p>
+              <p><span>项目top</span>{{ dataView.cost[1].cost | decimalsHandle }}</p>
+              <p><span>数据库均值</span>{{ dataView.cost[2].cost | decimalsHandle }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>点击数</h3>
+              <p
+                :style="{
+                  color: dataView.click[0].click > dataView.click[2].click ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.click[0].click }}
+              </p>
+              <p><span>项目top</span>{{ dataView.click[1].click }}</p>
+              <p><span>数据库均值</span>{{ dataView.click[2].click }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>曝光数</h3>
+              <p
+                :style="{
+                  color:
+                    dataView.materialShow[0].materialShow > dataView.materialShow[2].materialShow
+                      ? '#F66C6D'
+                      : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.materialShow[0].materialShow }}
+              </p>
+              <p><span>项目top</span>{{ dataView.materialShow[1].materialShow }}</p>
+              <p><span>数据库均值</span>{{ dataView.materialShow[2].materialShow }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>完播率</h3>
+              <p
+                :style="{
+                  color:
+                    dataView.play100Rate[0].play100Rate > dataView.play100Rate[2].play100Rate ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ (dataView.play100Rate[0].play100Rate * 100).toFixed(2) + '%' }}
+              </p>
+              <p><span>项目top</span>{{ (dataView.play100Rate[1].play100Rate * 100).toFixed(2) + '%' }}</p>
+              <p><span>数据库均值</span>{{ (dataView.play100Rate[2].play100Rate * 100).toFixed(2) + '%' }}</p>
+            </a-col>
+          </a-row>
+          <a-row :gutter="15" style="margin-top: 20px">
+            <a-col :xl="6" class="show-data">
+              <h3>点赞数</h3>
+              <p
+                :style="{
+                  color:
+                    dataView.likeMaterial[0].likeMaterial > dataView.likeMaterial[2].likeMaterial
+                      ? '#F66C6D'
+                      : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.likeMaterial[0].likeMaterial }}
+              </p>
+              <p><span>项目top</span>{{ dataView.likeMaterial[1].likeMaterial }}</p>
+              <p><span>数据库均值</span>{{ dataView.likeMaterial[2].likeMaterial }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>评论数</h3>
+              <p
+                :style="{
+                  color:
+                    dataView.commentMaterial[0].commentMaterial > dataView.commentMaterial[2].commentMaterial
+                      ? '#F66C6D'
+                      : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.commentMaterial[0].commentMaterial }}
+              </p>
+              <p><span>项目top</span>{{ dataView.commentMaterial[1].commentMaterial }}</p>
+              <p><span>数据库均值</span>{{ dataView.commentMaterial[2].commentMaterial }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>转发数</h3>
+              <p
+                :style="{
+                  color:
+                    dataView.shareMaterial[0].shareMaterial > dataView.shareMaterial[2].shareMaterial
+                      ? '#F66C6D'
+                      : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.shareMaterial[0].shareMaterial }}
+              </p>
+              <p><span>项目top</span>{{ dataView.shareMaterial[1].shareMaterial }}</p>
+              <p><span>数据库均值</span>{{ dataView.shareMaterial[2].shareMaterial }}</p>
+            </a-col>
+            <a-col :xl="6" class="show-data">
+              <h3>关注数</h3>
+              <p
+                :style="{
+                  color: dataView.follow[0].follow > dataView.follow[2].follow ? '#F66C6D' : '#67C239',
+                }"
+                style="font-size: 18px; font-weight: 700"
+              >
+                {{ dataView.follow[0].follow }}
+              </p>
+              <p><span>项目top</span>{{ dataView.follow[1].follow }}</p>
+              <p><span>数据库均值</span>{{ dataView.follow[2].follow }}</p>
+            </a-col>
+          </a-row>
+        </a-card>
+        <a-card class="search-box" style="min-height: 300px" title="数据消耗趋势">
+          <div
+            id="echartCircular"
+            ref="echartCircular"
+            style="height: 350px"
+            :style="{ width: (clientWidth / 24) * 18 - 48 - 24 + 'px' }"
+          ></div
+        ></a-card>
+        <!-- <a-card class="search-box" style="min-height: 300px; margin: 20px 0"> </a-card> -->
+      </a-col>
+    </a-spin>
+  </a-row>
+</template>
+
+<script>
+import { getAction, postAction } from '@/api/manage'
+import moment from 'moment'
+import $ from 'jquery'
+import qs from 'qs'
+import UploadToAli from '@femessage/upload-to-ali'
+import uploadFile from '@/components/uploadFile.vue'
+import { mapActions, mapGetters, mapState } from 'vuex'
+var echarts = require('echarts')
+export default {
+  name: 'online-training-list',
+  data() {
+    return {
+      materialInfo: null,
+      dataView: null,
+      clientWidth: 1920,
+      spinning: false,
+    }
+  },
+  components: {
+    UploadToAli,
+    uploadFile,
+  },
+  methods: {
+    handlerEchartOption(data) {
+      var option = {
+        noDataLoadingOption: {
+          text: '暂无数据',
+          effect: 'bubble',
+          effectOption: {
+            effect: {
+              n: 0,
+            },
+          },
+        },
+        // title: {
+        //     text: '折线图堆叠'
+        // },
+        tooltip: {
+          trigger: 'axis',
+        },
+        // legend: {
+        //     data: ['邮件营销', '联盟广告', ]
+        // },
+        grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true,
+        },
+        legend: {
+          icon: 'circle',
+          top: '5%',
+          right: '5%',
+          itemWidth: 6,
+          itemGap: 20,
+          textStyle: {
+            color: '#556677',
+          },
+        },
+        toolbox: {
+          // feature: {
+          //     saveAsImage: {}
+          // }
+        },
+        xAxis: {
+          type: 'category',
+          data: data.map((item) => {
+            return item.statDate
+          }),
+          boundaryGap: false,
+          // 坐标轴线
+          axisLine: {
+            show: false,
+            lineStyle: {
+              color: '#999',
+            },
+          },
+          // 分割线
+          splitLine: {
+            show: true,
+            lineStyle: {
+              type: 'dashed',
+              color: '#e5e5e5',
+            },
+          },
+        },
+        yAxis: {
+          type: 'value',
+          axisLine: {
+            show: false,
+            lineStyle: {
+              color: '#999',
+            },
+          },
+          splitLine: {
+            lineStyle: {
+              type: 'dashed',
+              color: '#e5e5e5',
+            },
+          },
+        },
+        series: [
+          {
+            name: '消耗',
+            type: 'line',
+            stack: '总量',
+            data: data.map((item) => {
+              return item.cost.toFixed(3)
+            }),
+            symbol: 'circle',
+            symbolSize: 1,
+            lineStyle: {
+              normal: {
+                width: 2,
+                // color: '#0bcd74'
+              },
+            },
+            itemStyle: {
+              borderColor: '#ffffff',
+              borderWidth: 0,
+            },
+          },
+        ],
+      }
+
+      return option
+    },
+    initEchart(idName, optionName) {
+      var that = this
+      const chart = this.$refs[idName]
+      //   console.log(chart)
+      if (chart) {
+        const myChart = echarts.init(document.getElementById(idName))
+        // myChart.showLoading({
+        //     text: "图表数据正在努力加载..."
+        // });
+
+        myChart.setOption(optionName)
+        window.addEventListener('resize', function () {
+          that.clientWidth = document.documentElement.clientWidth - 224
+          myChart.resize()
+        })
+      }
+    },
+    getMaterialInfo() {
+      this.spinning = true
+      var params = {
+        mediaId: this.$route.query.mediaId,
+        md5: this.$route.query.md5,
+      }
+      var data = []
+      this.postDataAction('/overView/materialDetailInfo', params).then((res) => {
+        if (res.success) {
+          this.materialInfo = res.result
+          
+        }
+      })
+      this.postDataAction('/overView/materialDetailAnalyse', params).then((res) => {
+        if (res.success) {
+          this.dataView = res.result
+           this.spinning = false
+        }
+      })
+      this.postDataAction('/overView/materialDetailChat', params).then((res) => {
+        if (res.success) {
+          this.initEchart('echartCircular', this.handlerEchartOption(res.result))
+          
+        }
+      })
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.clientWidth = document.documentElement.clientWidth - 224
+      //   this.$route.query.mediaId
+      //   this.$route.query.md5
+      this.getMaterialInfo()
+    })
+  },
+  created() {
+    
+  },
+}
+</script>

+ 680 - 0
src/views/modules/Statistics/materialReport/marterialList.vue

@@ -0,0 +1,680 @@
+<style>
+.materialReport .chart-card-content {
+  display: none !important;
+}
+</style>
+<style scoped>
+.top-ul-style {
+  width: 100%;
+  padding-left: 0;
+}
+.top-ul-style li {
+  height: 100px;
+  border: 1px solid #f2f2f2;
+  margin-bottom: 5px;
+  padding: 10px;
+  display: flex;
+  justify-content: space-between;
+}
+.li-cost {
+  display: flex;
+  flex-flow: column;
+  justify-content: center;
+  align-content: flex-end;
+}
+.li-cost span {
+  font-size: 16px;
+  font-weight: 500;
+  min-width: 50px;
+  text-align: right;
+}
+</style>
+<template>
+  <div class="materialReport">
+    <div class="card-container">
+      <div class="option" style="justify-content: space-between">
+        <div class="option" style="padding: 0">
+          <div class="item">
+            <span>素材ID</span>
+            <a-input style="width: 300px" v-model="md5"></a-input>
+          </div>
+        </div>
+
+        <div class="item" style="float: right">
+          <a-button @click="handleSubmit" type="primary" :loading="loading">搜索</a-button>
+          <a-button @click="resetSubmit" style="margin-left: 15px" :loading="loading">重置</a-button>
+        </div>
+      </div>
+    </div>
+    <a-row :gutter="24" style="margin-top: 20px">
+      <a-col :xl="24">
+        <a-card title="数据列表" style="width: 100%; min-height: 700px" :bordered="false">
+          <div class="tableTop" style="text-align: end; margin: 0 0 15px 0">
+            <!-- <a-button type="primary" class="export" @click="exportExcel">导出报表</a-button> -->
+            <a-button type="primary" class="add" @click="customColumns">自定义列</a-button>
+          </div>
+          <a-table
+            size="middle"
+            :columns="columns"
+            :dataSource="tableData"
+            bordered
+            id="outTable"
+            :pagination="ipagination"
+            :scroll="{ x: scrollX }"
+            :loading="loading"
+            ref="accountTable"
+            :customRow="rowClick"
+            :width="tableWidth"
+            @change="sort"
+            style="word-break: break-all; font-size: 16px; font-weight: 600"
+          >
+            <span slot="coverUrl" slot-scope="text, records">
+              <img :src="text || noImg" alt="" style="width: 100%; height: auto" />
+            </span>
+            <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+            <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span>
+            <span slot="clickMaterial" slot-scope="clickMaterial">{{ clickMaterial | formatCurrency }}</span>
+            <span slot="showMaterial" slot-scope="showMaterial">{{ showMaterial | formatCurrency }}</span>
+            <span slot="convertMaterial" slot-scope="convertMaterial">{{ convertMaterial | formatCurrency }}</span>
+            <span slot="play25FeedBreak" slot-scope="play25FeedBreak">{{ play25FeedBreak | formatCurrency }}</span>
+            <span slot="play50FeedBreak" slot-scope="play50FeedBreak">{{ play50FeedBreak | formatCurrency }}</span>
+            <span slot="play75FeedBreak" slot-scope="play75FeedBreak">{{ play75FeedBreak | formatCurrency }}</span>
+            <span slot="play100FeedBreak" slot-scope="play100FeedBreak">{{ play100FeedBreak | formatCurrency }}</span>
+            <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+            <span slot="downloadFinish" slot-scope="downloadFinish">{{ downloadFinish | formatCurrency }}</span>
+            <span slot="downloadStart" slot-scope="downloadStart">{{ downloadStart | formatCurrency }}</span>
+            <span slot="likeMaterial" slot-scope="likeMaterial">{{ likeMaterial | formatCurrency }}</span>
+            <span slot="shareMaterial" slot-scope="shareMaterial">{{ shareMaterial | formatCurrency }}</span>
+            <span slot="register" slot-scope="register">{{ register | formatCurrency }}</span>
+            <span slot="follow" slot-scope="follow">{{ follow | formatCurrency }}</span>
+            <span slot="formCount" slot-scope="formCount">{{ formCount | formatCurrency }}</span>
+            <span slot="formCountCost" slot-scope="formCountCost">{{ formCountCost | decimalsHandle }}</span>
+            <span slot="aClick" slot-scope="aClick">{{ aClick | formatCurrency }}</span>
+            <span slot="photoShow" slot-scope="photoShow">{{ photoShow | formatCurrency }}</span>
+            <span slot="photoClick" slot-scope="photoClick">{{ photoClick | formatCurrency }}</span>
+            <span slot="bClick" slot-scope="bClick">{{ bClick | formatCurrency }}</span>
+            <span slot="active" slot-scope="active">{{ active | formatCurrency }}</span>
+            <span slot="submit" slot-scope="submit">{{ submit | formatCurrency }}</span>
+            <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+            <span slot="eventCreditGrantLandingPage" slot-scope="eventCreditGrantLandingPage">{{
+              eventCreditGrantLandingPage | formatCurrency
+            }}</span>
+            <span slot="submitCost" slot-scope="submitCost">{{ submitCost | decimalsHandle }}</span>
+            <span slot="eventCreditGrantLandingPageCost" slot-scope="eventCreditGrantLandingPageCost">{{
+              eventCreditGrantLandingPageCost | decimalsHandle
+            }}</span>
+            <span slot="submitRate" slot-scope="submitRate">{{ submitRate | toPercentage }}</span>
+            <span slot="eventCreditGrantLandingPageRate" slot-scope="eventCreditGrantLandingPageRate">{{
+              eventCreditGrantLandingPageRate | toPercentage
+            }}</span>
+            <span slot="play25FeedBreakRate" slot-scope="play25FeedBreakRate">{{
+              play25FeedBreakRate | toPercentage
+            }}</span>
+            <span slot="playOverRate" slot-scope="playOverRate">{{ playOverRate | toPercentage }}</span>
+            <!-- 新加数据 -->
+
+            <span slot="convertRate" slot-scope="convertRate">{{ convertRate | toPercentage }}</span>
+            <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+            <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+            <span slot="cpc" slot-scope="cpc">{{ cpc | decimalsHandle }}</span>
+            <span slot="cpm" slot-scope="cpm">{{ cpm | decimalsHandle }}</span>
+            <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+            <span slot="installFinishRate" slot-scope="installFinishRate">{{ installFinishRate | toPercentage }}</span>
+            <span slot="validPlayRate" slot-scope="validPlayRate">{{ validPlayRate | toPercentage }}</span>
+            <span slot="activePayCost" slot-scope="activePayCost">{{ activePayCost | decimalsHandle }}</span>
+            <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+            <span slot="validPlayCost" slot-scope="validPlayCost">{{ validPlayCost | decimalsHandle }}</span>
+            <span slot="activeCost" slot-scope="activeCost">{{ activeCost | decimalsHandle }}</span>
+            <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+            <span slot="gameAddictionCost" slot-scope="gameAddictionCost">{{
+              gameAddictionCost | decimalsHandle
+            }}</span>
+            <span slot="downloadFinishCost" slot-scope="downloadFinishCost">{{
+              downloadFinishCost | decimalsHandle
+            }}</span>
+            <span slot="downloadStartCost" slot-scope="downloadStartCost">{{
+              downloadStartCost | decimalsHandle
+            }}</span>
+            <span slot="installFinishCost" slot-scope="installFinishCost">{{
+              installFinishCost | decimalsHandle
+            }}</span>
+            <span slot="convertCost" slot-scope="convertCost">{{ convertCost | decimalsHandle }}</span>
+
+            <!--  -->
+            <span slot="downloadStartRate" slot-scope="downloadStartRate">{{ downloadStartRate | toPercentage }}</span>
+            <span slot="downloadFinishRate" slot-scope="downloadFinishRate">{{
+              downloadFinishRate | toPercentage
+            }}</span>
+            <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+            <span slot="activeRegisterRate" slot-scope="activeRegisterRate">{{
+              activeRegisterRate | toPercentage
+            }}</span>
+            <span slot="gameAddictionRate" slot-scope="gameAddictionRate">{{ gameAddictionRate | toPercentage }}</span>
+            <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+            <!-- <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span> -->
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+    <a-modal title="查看视频" v-model="visibleVideo" :width="400" :footer="null">
+      <video class="video" :src="videoUrlShow" controls="controls" style="width: 100%">
+        您的浏览器不支持 video 标签。
+      </video>
+    </a-modal>
+    <customColumn
+      :visible="visible"
+      :listNum="listNum"
+      :fiexColumn="columnsFixd"
+      :mediaType="2"
+      @closeCustomColumn="closeCustomColumn"
+      @changeColumn="changeColumn"
+    />
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import YoutTable from '@/components/youtTable/YoutTable'
+import ChartCard from '@/components/ChartCard'
+import Trend from '@/components/Trend'
+import { mapGetters } from 'vuex'
+import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
+import customColumn from '../components/customColumn.vue'
+var echarts = require('echarts')
+
+const columnsFixd = [
+  {
+    title: '素材',
+    dataIndex: 'coverUrl',
+    scopedSlots: { customRender: 'coverUrl' },
+    align: 'center',
+    key: 'date',
+    width: 200,
+    fixed: 'left',
+  },
+  {
+    title: '素材名称',
+    dataIndex: 'materialName',
+    align: 'center',
+    width: 200,
+    fixed: 'left',
+    customRender: function (text) {
+      if (text) {
+        return text
+      } else {
+        return '-'
+      }
+    },
+  },
+  {
+    title: '所属项目',
+    dataIndex: 'projectName',
+    align: 'center',
+    width: 200,
+    fixed: 'left',
+  },
+]
+
+const initVariableColimns = [
+  {
+    title: '消耗(元)',
+    dataIndex: 'cost',
+    width: 150,
+    tip: '广告在投放期间的花费总额',
+    align: 'center',
+    scopedSlots: { customRender: 'cost' },
+    sorter: () => {},
+  },
+  // {
+  //     title: '折后消耗(元)',
+  //     dataIndex: 'discountCost',
+  //     width:150,
+  //     tip: '广告在投放期间的花费总额',
+  //     align: 'center',
+  //     scopedSlots: { customRender: 'discountCost' },
+  //     sorter: () => {}
+  // },
+  {
+    title: '封面曝光数',
+    dataIndex: 'photoShow',
+    tip: '广告在瀑布流被观看次数',
+    align: 'center',
+    scopedSlots: { customRender: 'photoShow' },
+    sorter: () => {},
+  },
+  {
+    title: '封面点击数',
+    dataIndex: 'photoClick',
+    tip: '用户点击封面进入视频播放页的次数(数据会进行反作弊去重)',
+    align: 'center',
+
+    scopedSlots: { customRender: 'photoClick' },
+    sorter: () => {},
+  },
+  {
+    title: '封面点击率',
+    dataIndex: 'clickRate',
+    tip: '封面点击数占封面展示数百分比',
+    align: 'center',
+    scopedSlots: { customRender: 'clickRate' },
+    sorter: () => {},
+  },
+  {
+    title: '素材曝光数',
+    dataIndex: 'aClick',
+    tip: '用户进入视频播放页观看的次数(数据会进行反作弊去重)',
+    align: 'center',
+
+    scopedSlots: { customRender: 'aClick' },
+    sorter: () => {},
+  },
+  {
+    title: '行为数',
+    dataIndex: 'bClick',
+    tip: '用户在视频播放页单击转化按钮的次数/展示数*100%',
+    align: 'center',
+
+    scopedSlots: { customRender: 'bClick' },
+    sorter: () => {},
+  },
+
+  {
+    title: '行为率',
+    dataIndex: 'bClickRate',
+    tip: '行为数占素材曝光数百分比',
+    align: 'center',
+    scopedSlots: { customRender: 'bClickRate' },
+    sorter: () => {},
+  },
+  {
+    title: '平均千次封面曝光花费(元)',
+    dataIndex: 'cpm',
+    tip: '花费/封面曝光数*1000',
+    align: 'center',
+    scopedSlots: { customRender: 'cpm' },
+    sorter: () => {},
+  },
+  {
+    title: '平均封面点击单价(元)',
+    dataIndex: 'cpc',
+    tip: '花费/封面点击数',
+    align: 'center',
+    scopedSlots: { customRender: 'cpc' },
+    sorter: () => {},
+  },
+  {
+    title: '平均行为单价(元)',
+    dataIndex: 'cpb',
+    tip: '总花费/行为数',
+    align: 'center',
+    scopedSlots: { customRender: 'cpb' },
+    sorter: () => {},
+  },
+]
+export default {
+  components: {
+    YoutTable,
+    ChartCard,
+    Trend,
+    customColumn,
+  },
+  data() {
+    return {
+      tableData: [],
+      designTopLoading: false,
+      noImg: require('@/assets/noImg.png'),
+      visibleVideo: false,
+      videoUrlShow: '',
+      cost: '0',
+      costLink: 0,
+      videoTotal: '0',
+      newVideo: 0,
+      hotTotal: '0',
+      xiaoTotal: '0',
+      spinning: false,
+      loading: false,
+      chartList: [],
+      videoList: [],
+      designTopList: [],
+      columns: [...columnsFixd, ...initVariableColimns], //table的表头
+      columnsFixd,
+      ipagination: {
+        current: 1,
+        pageSize: 10,
+        //   pageSizeOptions: ['10', '20', '30'],
+        showTotal: (total, range) => {
+          return range[0] + '-' + range[1] + ' 共' + total + '条'
+        },
+        showQuickJumper: true,
+        // showSizeChanger: true,
+        // pageSizeOptions: ['10', '30', '50'],
+        total: 0,
+        onChange: (current, pageSize) => {
+          // 切换分页时的回调,
+          // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+          this.ipagination.current = current
+          this.ipagination.pageSize = pageSize
+        },
+      },
+
+      dateRanges: {
+        今天: [moment(), moment()],
+        昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
+        近一周: [moment().subtract(7, 'days'), moment()],
+        近一月: [moment().subtract(1, 'months'), moment()],
+        近半年: [moment().subtract(6, 'months'), moment()],
+        近一年: [moment().subtract(12, 'months'), moment()],
+      },
+      dateValue: [moment().subtract(7, 'days'), moment()],
+      dataDimension: 'a',
+      mediaDimension: 'b',
+      dataDimensionValue: [],
+      dataDimensionList: [],
+      specificLoading: false,
+      order: null,
+      target: null,
+      materialData: null,
+      md5: '',
+      visible: false,
+      listNum: [],
+      scrollX: 1000,
+      tableWidth: '', //设置表格的列宽
+    }
+  },
+  watch: {
+    visibleVideo(n, o) {
+      if (!n) {
+        stopOtherVideo()
+        closeAllVideoFun()
+      }
+    },
+    'ipagination.current': function (n, o) {
+      if (n != o) {
+        this.getMoreVideoList({
+          ...this.materialData,
+        })
+      }
+    },
+  },
+  methods: {
+    rowClick(record, index) {
+      return {
+        on: {
+          click: (e) => {
+            this.$router.push({
+              path: '/materialReport/marterialDetail?md5=' + record.signature + '&mediaId=2',
+            })
+          },
+        },
+      }
+    },
+    moment,
+    closeCustomColumn() {
+      this.visible = false
+    },
+    changeColumn(val) {
+      this.columns = [...val]
+      if (this.columns.length > this.columnsFixd.length && this.columns.length < 8) {
+        this.columns.forEach((element, index) => {
+          if (index < this.columns.length - 1) {
+            element.width = 'auto'
+            element.fixed = false
+          }
+        })
+
+        // this.scrollX=2000+200*(this.columns.length-this.columnsFixd.length)
+      } else if (this.columns.length >= 8) {
+        this.columns.forEach((element, index) => {
+          if (index < this.columnsFixd.length) {
+            element.width = 200
+            element.fixed = 'left'
+          }
+        })
+
+        this.scrollX = 1000 + 200 * (this.columns.length - this.columnsFixd.length)
+      } else {
+        this.scrollX = 0
+        this.columns.forEach((element) => {
+          element.width = 'auto'
+          element.fixed = false
+        })
+      }
+    },
+    customColumns() {
+      this.visible = true
+      this.listNum = [...this.columns]
+    },
+    ...mapGetters(['userInfo']),
+    filterOption(input, option) {
+      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+    },
+    sort(pagination, filters, sorter, { currentDataSource }) {
+      // console.log(pagination, filters, sorter)
+      this.ipagination.current = pagination.current
+      this.ipagination.pageSize = pagination.pageSize
+      if (sorter.order) {
+        this.order = sorter.order ? sorter.order : 'descend'
+        this.target = sorter.columnKey
+        this.getMoreVideoList({
+          ...this.materialData,
+          target: sorter.columnKey,
+          order: sorter.order ? sorter.order : 'descend',
+        })
+      } else {
+        this.order = null
+        this.target = null
+      }
+    },
+    getData() {
+      var data = { ...this.materialData, md5: this.md5 }
+      this.getMoreVideoList(data)
+    },
+
+    getMoreVideoList(data) {
+      this.loading = true
+      var params = { ...data }
+      params.channelType = null
+
+      if (data.target) {
+        params.target = data.target
+        if (data.order == 'descend') {
+          params.order = 'desc'
+        } else {
+          params.order = 'asc'
+        }
+      } else {
+        params.target = this.target
+        params.order = this.order == 'descend' ? 'desc' : this.order == null ? null : 'asc'
+      }
+
+      params.pageSize = this.ipagination.pageSize
+      params.pageNo = this.ipagination.current
+      this.postDataAction('/overView/materialTopViewMore', params).then((res) => {
+        this.loading = false
+        if (res.success) {
+          this.tableData = res.result.list
+          this.ipagination.total = res.result.total
+        }
+      })
+    },
+    getDesignTopList(data) {
+      this.designTopLoading = true
+      return new Promise((resolve, reject) => {
+        var params = {
+          // startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
+          // endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
+          // userId: this.userInfo().id,
+          // pageSize: this.ipagination.pageSize,
+          // pageNo: this.ipagination.current,
+          // target: 'cost',
+          // order: 'desc',
+        }
+        params.startDate = this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
+        params.endDate = this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
+        params.userId = this.userInfo().id
+        params.pageSize = this.ipagination.pageSize
+        params.pageNo = this.ipagination.current
+
+        if (data) {
+          params.target = data.target
+          if (data.order == 'descend') {
+            params.order = 'desc'
+          } else {
+            params.order = 'asc'
+          }
+        } else {
+          params.target = this.target
+          params.order = this.order == 'descend' ? 'desc' : 'asc'
+        }
+        this.postDataAction('/overView/designTop', params).then((res) => {
+          this.designTopLoading = false
+          if (res.success) {
+            this.designTopList = res.result.list
+            this.ipagination.total = res.result.total
+            resolve(res.result)
+          } else {
+            reject(res.message)
+          }
+        })
+      })
+    },
+
+    handleSubmit() {
+      this.spinning = true
+      this.ipagination.current = 1
+      this.getData()
+    },
+    resetSubmit() {
+      this.dateValue = [moment().subtract(7, 'days'), moment()]
+      this.dataDimension = 'a'
+      this.mediaDimension = 'b'
+      this.dataDimensionValue = []
+      this.ipagination.current = 1
+      this.md5 = ''
+      this.getData()
+    },
+    //导出报表
+    exportExcel() {
+      
+      let column = this.columns.map((item, index) => {
+        return item.dataIndex
+      })
+      let columns = column.splice(3)
+      
+      downFilePost('/ctop/kuaishou/dailyPage/report/excel', {
+        mediaId: this.mediaId,
+        discount: this.discount,
+        accountIds: this.accountId,
+        startDate: this.dateValue[0].format('YYYY-MM-DD'),
+        endDate: this.dateValue[1].format('YYYY-MM-DD'),
+        hour: this.timeSelectValue,
+        target: this.target,
+        order: this.order,
+        columns,
+      }).then((res) => {
+        let blob = new Blob([res], {
+          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        })
+        let downloadElement = document.createElement('a')
+        let href = window.URL.createObjectURL(blob) //创建下载的链接
+        downloadElement.href = href
+        downloadElement.download = moment().format('YYYY-MM-DD') + '账户报表.xlsx' //下载后文件名
+        document.body.appendChild(downloadElement)
+        downloadElement.click() //点击下载
+        document.body.removeChild(downloadElement) //下载完成移除元素
+        window.URL.revokeObjectURL(href) //释放掉blob对象
+      })
+    },
+    tableChange(data) {
+      console.log(data)
+    },
+    //获取echart的值
+    initEchart(idName, optionName) {
+      const chart = this.$refs[idName]
+      //   console.log(chart)
+      if (chart) {
+        const myChart = echarts.init(document.getElementById(idName))
+        // myChart.showLoading({
+        //     text: "图表数据正在努力加载..."
+        // });
+
+        myChart.setOption(optionName)
+        window.addEventListener('resize', function () {
+          myChart.resize()
+        })
+      }
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.materialData = JSON.parse(localStorage.getItem('materialParams'))
+      this.getMoreVideoList(this.materialData)
+    })
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.materialReport {
+  .option {
+    background: white;
+    padding: 20px;
+    display: flex;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+    .item {
+      margin-right: 15px;
+      margin-bottom: 15px;
+      height: 32px;
+      line-height: 32px;
+      flex-shrink: 0;
+      span {
+        margin-right: 10px;
+      }
+    }
+  }
+  .echart {
+    margin-top: 20px;
+    padding: 0 20px 20px;
+    background: white;
+    .echart-header {
+      padding: 20px 0;
+      font-size: 15px;
+      font-weight: 600;
+    }
+  }
+  .tableBody {
+    margin-top: 20px;
+  }
+}
+</style>
+<style>
+.card-container {
+  overflow: hidden;
+  /* padding: 24px; */
+}
+.card-container > .ant-tabs-card > .ant-tabs-content {
+  /* height: 120px; */
+  margin-top: -16px;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
+  background: #fff;
+  /* padding: 16px; */
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar {
+  border-color: #fff;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
+  border-color: transparent;
+  background: transparent !important;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
+  border-color: #fff;
+  background: #fff !important;
+}
+</style>

+ 633 - 0
src/views/modules/Statistics/materialReport/marterialTtList.vue

@@ -0,0 +1,633 @@
+<style>
+.materialReport .chart-card-content {
+  display: none !important;
+}
+</style>
+<style scoped>
+.top-ul-style {
+  width: 100%;
+  padding-left: 0;
+}
+.top-ul-style li {
+  height: 100px;
+  border: 1px solid #f2f2f2;
+  margin-bottom: 5px;
+  padding: 10px;
+  display: flex;
+  justify-content: space-between;
+}
+.li-cost {
+  display: flex;
+  flex-flow: column;
+  justify-content: center;
+  align-content: flex-end;
+}
+.li-cost span {
+  font-size: 16px;
+  font-weight: 500;
+  min-width: 50px;
+  text-align: right;
+}
+</style>
+<template>
+  <div class="materialReport">
+    <div class="card-container">
+      <div class="option" style="justify-content: space-between">
+        <div class="option" style="padding: 0">
+          <div class="item">
+            <span>素材ID</span>
+            <a-input style="width: 300px" v-model="md5"></a-input>
+          </div>
+        </div>
+
+        <div class="item" style="float: right">
+          <a-button @click="handleSubmit" type="primary" :loading="spinning">搜索</a-button>
+          <a-button @click="resetSubmit" style="margin-left: 15px" :loading="spinning">重置</a-button>
+        </div>
+      </div>
+    </div>
+    <a-row :gutter="24" style="margin-top: 20px">
+      <a-col :xl="24">
+        <a-card title="数据列表" style="width: 100%; min-height: 700px" :bordered="false">
+          <div class="tableTop" style="text-align: end; margin: 0 0 15px 0">
+            <!-- <a-button type="primary" class="export" @click="exportExcel">导出报表</a-button> -->
+            <a-button type="primary" class="add" @click="customColumns">自定义列</a-button>
+          </div>
+          <a-table
+            size="middle"
+            :columns="columns"
+            :dataSource="tableData"
+            bordered
+            id="outTable"
+            :pagination="ipagination"
+            :scroll="{ x: scrollX }"
+            :loading="loading"
+            ref="accountTable"
+            :width="tableWidth"
+            :customRow="rowClick"
+            @change="sort"
+            style="word-break: break-all; font-size: 16px; font-weight: 600"
+          >
+            <span slot="coverUrl" slot-scope="text, records">
+              <img :src="text || noImg" alt="" style="width: 100%; height: auto" />
+            </span>
+            <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+            <span slot="cost" slot-scope="cost">{{ cost | decimalsHandle }}</span>
+            <span slot="clickMaterial" slot-scope="clickMaterial">{{ clickMaterial | formatCurrency }}</span>
+            <span slot="showMaterial" slot-scope="showMaterial">{{ showMaterial | formatCurrency }}</span>
+            <span slot="convertMaterial" slot-scope="convertMaterial">{{ convertMaterial | formatCurrency }}</span>
+            <span slot="play25FeedBreak" slot-scope="play25FeedBreak">{{ play25FeedBreak | formatCurrency }}</span>
+            <span slot="play50FeedBreak" slot-scope="play50FeedBreak">{{ play50FeedBreak | formatCurrency }}</span>
+            <span slot="play75FeedBreak" slot-scope="play75FeedBreak">{{ play75FeedBreak | formatCurrency }}</span>
+            <span slot="play100FeedBreak" slot-scope="play100FeedBreak">{{ play100FeedBreak | formatCurrency }}</span>
+            <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+            <span slot="downloadFinish" slot-scope="downloadFinish">{{ downloadFinish | formatCurrency }}</span>
+            <span slot="downloadStart" slot-scope="downloadStart">{{ downloadStart | formatCurrency }}</span>
+            <span slot="likeMaterial" slot-scope="likeMaterial">{{ likeMaterial | formatCurrency }}</span>
+            <span slot="shareMaterial" slot-scope="shareMaterial">{{ shareMaterial | formatCurrency }}</span>
+            <span slot="register" slot-scope="register">{{ register | formatCurrency }}</span>
+            <span slot="follow" slot-scope="follow">{{ follow | formatCurrency }}</span>
+            <span slot="formCount" slot-scope="formCount">{{ formCount | formatCurrency }}</span>
+            <span slot="formCountCost" slot-scope="formCountCost">{{ formCountCost | decimalsHandle }}</span>
+            <span slot="aClick" slot-scope="aClick">{{ aClick | formatCurrency }}</span>
+            <span slot="photoShow" slot-scope="photoShow">{{ photoShow | formatCurrency }}</span>
+            <span slot="photoClick" slot-scope="photoClick">{{ photoClick | formatCurrency }}</span>
+            <span slot="bClick" slot-scope="bClick">{{ bClick | formatCurrency }}</span>
+            <span slot="active" slot-scope="active">{{ active | formatCurrency }}</span>
+            <span slot="submit" slot-scope="submit">{{ submit | formatCurrency }}</span>
+            <span slot="nextDayOpen" slot-scope="nextDayOpen">{{ nextDayOpen | formatCurrency }}</span>
+            <span slot="eventCreditGrantLandingPage" slot-scope="eventCreditGrantLandingPage">{{
+              eventCreditGrantLandingPage | formatCurrency
+            }}</span>
+            <span slot="submitCost" slot-scope="submitCost">{{ submitCost | decimalsHandle }}</span>
+            <span slot="eventCreditGrantLandingPageCost" slot-scope="eventCreditGrantLandingPageCost">{{
+              eventCreditGrantLandingPageCost | decimalsHandle
+            }}</span>
+            <span slot="submitRate" slot-scope="submitRate">{{ submitRate | toPercentage }}</span>
+            <span slot="eventCreditGrantLandingPageRate" slot-scope="eventCreditGrantLandingPageRate">{{
+              eventCreditGrantLandingPageRate | toPercentage
+            }}</span>
+            <span slot="play25FeedBreakRate" slot-scope="play25FeedBreakRate">{{
+              play25FeedBreakRate | toPercentage
+            }}</span>
+            <span slot="playOverRate" slot-scope="playOverRate">{{ playOverRate | toPercentage }}</span>
+            <!-- 新加数据 -->
+
+            <span slot="convertRate" slot-scope="convertRate">{{ convertRate | toPercentage }}</span>
+            <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+            <span slot="ctr" slot-scope="ctr">{{ ctr | toPercentage }}</span>
+            <span slot="cpc" slot-scope="cpc">{{ cpc | decimalsHandle }}</span>
+            <span slot="cpm" slot-scope="cpm">{{ cpm | decimalsHandle }}</span>
+            <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+            <span slot="installFinishRate" slot-scope="installFinishRate">{{ installFinishRate | toPercentage }}</span>
+            <span slot="validPlayRate" slot-scope="validPlayRate">{{ validPlayRate | toPercentage }}</span>
+            <span slot="activePayCost" slot-scope="activePayCost">{{ activePayCost | decimalsHandle }}</span>
+            <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+            <span slot="validPlayCost" slot-scope="validPlayCost">{{ validPlayCost | decimalsHandle }}</span>
+            <span slot="activeCost" slot-scope="activeCost">{{ activeCost | decimalsHandle }}</span>
+            <span slot="nextDayOpenCost" slot-scope="nextDayOpenCost">{{ nextDayOpenCost | decimalsHandle }}</span>
+            <span slot="gameAddictionCost" slot-scope="gameAddictionCost">{{
+              gameAddictionCost | decimalsHandle
+            }}</span>
+            <span slot="downloadFinishCost" slot-scope="downloadFinishCost">{{
+              downloadFinishCost | decimalsHandle
+            }}</span>
+            <span slot="downloadStartCost" slot-scope="downloadStartCost">{{
+              downloadStartCost | decimalsHandle
+            }}</span>
+            <span slot="installFinishCost" slot-scope="installFinishCost">{{
+              installFinishCost | decimalsHandle
+            }}</span>
+            <span slot="convertCost" slot-scope="convertCost">{{ convertCost | decimalsHandle }}</span>
+
+            <!--  -->
+            <span slot="downloadStartRate" slot-scope="downloadStartRate">{{ downloadStartRate | toPercentage }}</span>
+            <span slot="downloadFinishRate" slot-scope="downloadFinishRate">{{
+              downloadFinishRate | toPercentage
+            }}</span>
+            <span slot="activeRate" slot-scope="activeRate">{{ activeRate | toPercentage }}</span>
+            <span slot="activeRegisterRate" slot-scope="activeRegisterRate">{{
+              activeRegisterRate | toPercentage
+            }}</span>
+            <span slot="gameAddictionRate" slot-scope="gameAddictionRate">{{ gameAddictionRate | toPercentage }}</span>
+            <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span>
+            <!-- <span slot="nextDayOpenRate" slot-scope="nextDayOpenRate">{{ nextDayOpenRate | toPercentage }}</span> -->
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+    <a-modal title="查看视频" v-model="visibleVideo" :width="400" :footer="null">
+      <video class="video" :src="videoUrlShow" controls="controls" style="width: 100%">
+        您的浏览器不支持 video 标签。
+      </video>
+    </a-modal>
+    <customColumn
+      :visible="visible"
+      :listNum="listNum"
+      :fiexColumn="columnsFixd"
+      :mediaType="2"
+      @closeCustomColumn="closeCustomColumn"
+      @changeColumn="changeColumn"
+    />
+  </div>
+</template>
+
+<script>
+import moment from 'moment'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import YoutTable from '@/components/youtTable/YoutTable'
+import ChartCard from '@/components/ChartCard'
+import Trend from '@/components/Trend'
+import { mapGetters } from 'vuex'
+import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
+import customColumn from '../components/customColumn.vue'
+var echarts = require('echarts')
+
+const columnsFixd = [
+  {
+    title: '素材',
+    dataIndex: 'coverUrl',
+    scopedSlots: { customRender: 'coverUrl' },
+    align: 'center',
+    key: 'date',
+    width: 200,
+    fixed: 'left',
+  },
+  {
+    title: '素材名称',
+    dataIndex: 'materialName',
+    align: 'center',
+    width: 200,
+    fixed: 'left',
+    customRender: function (text) {
+      if (text) {
+        return text
+      } else {
+        return '-'
+      }
+    },
+  },
+  {
+    title: '所属项目',
+    dataIndex: 'projectName',
+    align: 'center',
+    width: 200,
+    fixed: 'left',
+  },
+]
+
+const initVariableColimns = [
+  {
+    title: '消耗(元)',
+    dataIndex: 'cost',
+    scopedSlots: { customRender: 'cost' },
+    align: 'center',
+    sorter: (a, b) => {},
+  },
+  {
+    title: '点击数',
+    dataIndex: 'clickMaterial',
+    align: 'center',
+    scopedSlots: { customRender: 'clickMaterial' },
+    sorter: (a, b) => {},
+    // (a, b) => a.clickMaterial - b.clickMaterial
+  },
+  {
+    title: '点击率',
+    dataIndex: 'ctr',
+    align: 'center',
+    scopedSlots: { customRender: 'ctr' },
+    sorter: (a, b) => {},
+  },
+
+  {
+    title: '展示数',
+    dataIndex: 'showMaterial',
+    align: 'center',
+
+    scopedSlots: { customRender: 'showMaterial' },
+    sorter: (a, b) => {},
+  },
+  {
+    title: '平均千次展现费用(元)',
+    dataIndex: 'cpm',
+    tip: '广告平均每一千次展现所付出的费用,计算公式是:总花费/展示数*1000',
+    align: 'center',
+
+    scopedSlots: { customRender: 'cpm' },
+    sorter: (a, b) => {},
+  },
+  {
+    title: '平均点击单价(元)',
+    dataIndex: 'cpc',
+    tip: '广告主为每次点击付出的费用成本,计算公式是:总花费/点击数',
+    align: 'center',
+    scopedSlots: { customRender: 'cpc' },
+    sorter: (a, b) => {},
+  },
+]
+export default {
+  components: {
+    YoutTable,
+    ChartCard,
+    Trend,
+    customColumn,
+  },
+  data() {
+    return {
+      tableData: [],
+      designTopLoading: false,
+      noImg: require('@/assets/noImg.png'),
+      visibleVideo: false,
+      videoUrlShow: '',
+      cost: '0',
+      costLink: 0,
+      videoTotal: '0',
+      newVideo: 0,
+      hotTotal: '0',
+      xiaoTotal: '0',
+      spinning: false,
+      loading: false,
+      chartList: [],
+      videoList: [],
+      designTopList: [],
+      columns: [...columnsFixd, ...initVariableColimns], //table的表头
+      columnsFixd,
+      ipagination: {
+        current: 1,
+        pageSize: 10,
+        //   pageSizeOptions: ['10', '20', '30'],
+        showTotal: (total, range) => {
+          return range[0] + '-' + range[1] + ' 共' + total + '条'
+        },
+        showQuickJumper: true,
+        // showSizeChanger: true,
+        // pageSizeOptions: ['10', '30', '50'],
+        total: 0,
+        onChange: (current, pageSize) => {
+          // 切换分页时的回调,
+          // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+          this.ipagination.current = current
+          this.ipagination.pageSize = pageSize
+        },
+      },
+
+      dateRanges: {
+        今天: [moment(), moment()],
+        昨天: [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
+        近一周: [moment().subtract(7, 'days'), moment()],
+        近一月: [moment().subtract(1, 'months'), moment()],
+        近半年: [moment().subtract(6, 'months'), moment()],
+        近一年: [moment().subtract(12, 'months'), moment()],
+      },
+      dateValue: [moment().subtract(7, 'days'), moment()],
+      dataDimension: 'a',
+      mediaDimension: 'b',
+      dataDimensionValue: [],
+      dataDimensionList: [],
+      specificLoading: false,
+      order: null,
+      target: null,
+      materialData: null,
+      md5: '',
+      visible: false,
+      listNum: [],
+      scrollX: 1000,
+      tableWidth: '', //设置表格的列宽
+    }
+  },
+  watch: {
+    visibleVideo(n, o) {
+      if (!n) {
+        stopOtherVideo()
+        closeAllVideoFun()
+      }
+    },
+    'ipagination.current': function (n, o) {
+      if (n != o) {
+        this.getMoreVideoList({
+          ...this.materialData,
+        })
+      }
+    },
+  },
+  methods: {
+    rowClick(record, index) {
+      return {
+        on: {
+          click: (e) => {
+            this.$router.push({
+              path: '/materialReport/marterialDetail?md5=' + record.signature + '&mediaId=1',
+            })
+          },
+        },
+      }
+    },
+
+    moment,
+    closeCustomColumn() {
+      this.visible = false
+    },
+    changeColumn(val) {
+      this.columns = [...val]
+      if (this.columns.length > this.columnsFixd.length && this.columns.length < 8) {
+        this.columns.forEach((element, index) => {
+          if (index < this.columns.length - 1) {
+            element.width = 'auto'
+            element.fixed = false
+          }
+        })
+
+        // this.scrollX=2000+200*(this.columns.length-this.columnsFixd.length)
+      } else if (this.columns.length >= 8) {
+        this.columns.forEach((element, index) => {
+          if (index < this.columnsFixd.length) {
+            element.width = 200
+            element.fixed = 'left'
+          }
+        })
+
+        this.scrollX = 1000 + 200 * (this.columns.length - this.columnsFixd.length)
+      } else {
+        this.scrollX = 0
+        this.columns.forEach((element) => {
+          element.width = 'auto'
+          element.fixed = false
+        })
+      }
+    },
+    customColumns() {
+      this.visible = true
+      this.listNum = [...this.columns]
+    },
+    ...mapGetters(['userInfo']),
+    filterOption(input, option) {
+      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+    },
+    sort(pagination, filters, sorter, { currentDataSource }) {
+      // console.log(pagination, filters, sorter)
+      this.ipagination.current = pagination.current
+      this.ipagination.pageSize = pagination.pageSize
+      if (sorter.order) {
+        this.order = sorter.order ? sorter.order : 'descend'
+        this.target = sorter.columnKey
+        this.getMoreVideoList({
+          ...this.materialData,
+          target: sorter.columnKey,
+          order: sorter.order ? sorter.order : 'descend',
+        })
+      } else {
+        this.order = null
+        this.target = null
+      }
+    },
+    getData() {
+      var data = { ...this.materialData, md5: this.md5 }
+      this.getMoreVideoList(data)
+    },
+
+    getMoreVideoList(data) {
+      this.loading = true
+      var params = { ...data }
+      params.channelType = null
+
+      if (data.target) {
+        params.target = data.target
+        if (data.order == 'descend') {
+          params.order = 'desc'
+        } else {
+          params.order = 'asc'
+        }
+      } else {
+        params.target = this.target
+        params.order = this.order == 'descend' ? 'desc' : this.order == null ? null : 'asc'
+      }
+
+      params.pageSize = this.ipagination.pageSize
+      params.pageNo = this.ipagination.current
+      this.postDataAction('/overView/materialTopViewMore', params).then((res) => {
+        this.loading = false
+        if (res.success) {
+          this.tableData = res.result.list
+          this.ipagination.total = res.result.total
+        }
+      })
+    },
+    getDesignTopList(data) {
+      this.designTopLoading = true
+      return new Promise((resolve, reject) => {
+        var params = {
+          // startDate: this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null,
+          // endDate: this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null,
+          // userId: this.userInfo().id,
+          // pageSize: this.ipagination.pageSize,
+          // pageNo: this.ipagination.current,
+          // target: 'cost',
+          // order: 'desc',
+        }
+        params.startDate = this.dateValue.length == 2 ? moment(this.dateValue[0]).format('YYYY-MM-DD') : null
+        params.endDate = this.dateValue.length == 2 ? moment(this.dateValue[1]).format('YYYY-MM-DD') : null
+        params.userId = this.userInfo().id
+        params.pageSize = this.ipagination.pageSize
+        params.pageNo = this.ipagination.current
+
+        if (data) {
+          params.target = data.target
+          if (data.order == 'descend') {
+            params.order = 'desc'
+          } else {
+            params.order = 'asc'
+          }
+        } else {
+          params.target = this.target
+          params.order = this.order == 'descend' ? 'desc' : 'asc'
+        }
+        this.postDataAction('/overView/designTop', params).then((res) => {
+          this.designTopLoading = false
+          if (res.success) {
+            this.designTopList = res.result.list
+            this.ipagination.total = res.result.total
+            resolve(res.result)
+          } else {
+            reject(res.message)
+          }
+        })
+      })
+    },
+
+    handleSubmit() {
+      this.ipagination.current = 1
+      this.getData()
+    },
+    resetSubmit() {
+      this.dateValue = [moment().subtract(7, 'days'), moment()]
+      this.dataDimension = 'a'
+      this.mediaDimension = 'b'
+      this.dataDimensionValue = []
+      this.ipagination.current = 1
+      this.md5 = ''
+      this.getData()
+    },
+    //导出报表
+    exportExcel() {
+      let column = this.columns.map((item, index) => {
+        return item.dataIndex
+      })
+      let columns = column.splice(3)
+      // console.log(columns)
+      downFilePost('/ctop/kuaishou/dailyPage/report/excel', {
+        mediaId: this.mediaId,
+        discount: this.discount,
+        accountIds: this.accountId,
+        startDate: this.dateValue[0].format('YYYY-MM-DD'),
+        endDate: this.dateValue[1].format('YYYY-MM-DD'),
+        hour: this.timeSelectValue,
+        target: this.target,
+        order: this.order,
+        columns,
+      }).then((res) => {
+        let blob = new Blob([res], {
+          type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        })
+        let downloadElement = document.createElement('a')
+        let href = window.URL.createObjectURL(blob) //创建下载的链接
+        downloadElement.href = href
+        downloadElement.download = moment().format('YYYY-MM-DD') + '账户报表.xlsx' //下载后文件名
+        document.body.appendChild(downloadElement)
+        downloadElement.click() //点击下载
+        document.body.removeChild(downloadElement) //下载完成移除元素
+        window.URL.revokeObjectURL(href) //释放掉blob对象
+      })
+    },
+    tableChange(data) {
+      console.log(data)
+    },
+    //获取echart的值
+    initEchart(idName, optionName) {
+      const chart = this.$refs[idName]
+      //   console.log(chart)
+      if (chart) {
+        const myChart = echarts.init(document.getElementById(idName))
+        // myChart.showLoading({
+        //     text: "图表数据正在努力加载..."
+        // });
+
+        myChart.setOption(optionName)
+        window.addEventListener('resize', function () {
+          myChart.resize()
+        })
+      }
+    },
+  },
+  mounted() {
+    this.$nextTick(() => {
+      this.materialData = JSON.parse(localStorage.getItem('materialParams'))
+      this.getMoreVideoList(this.materialData)
+    })
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.materialReport {
+  .option {
+    background: white;
+    padding: 20px;
+    display: flex;
+    justify-content: flex-start;
+    flex-wrap: wrap;
+    .item {
+      margin-right: 15px;
+      margin-bottom: 15px;
+      height: 32px;
+      line-height: 32px;
+      flex-shrink: 0;
+      span {
+        margin-right: 10px;
+      }
+    }
+  }
+  .echart {
+    margin-top: 20px;
+    padding: 0 20px 20px;
+    background: white;
+    .echart-header {
+      padding: 20px 0;
+      font-size: 15px;
+      font-weight: 600;
+    }
+  }
+  .tableBody {
+    margin-top: 20px;
+  }
+}
+</style>
+<style>
+.card-container {
+  overflow: hidden;
+  /* padding: 24px; */
+}
+.card-container > .ant-tabs-card > .ant-tabs-content {
+  /* height: 120px; */
+  margin-top: -16px;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-content > .ant-tabs-tabpane {
+  background: #fff;
+  /* padding: 16px; */
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar {
+  border-color: #fff;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab {
+  border-color: transparent;
+  background: transparent !important;
+}
+
+.card-container > .ant-tabs-card > .ant-tabs-bar .ant-tabs-tab-active {
+  border-color: #fff;
+  background: #fff !important;
+}
+</style>

File diff suppressed because it is too large
+ 859 - 457
src/views/modules/Statistics/materialReport/materialReport.vue


+ 17 - 6
src/views/system/modules/UserModal.vue

@@ -312,6 +312,13 @@ export default {
       this.userId = ''
     },
     add() {
+      this.disableSubmit = false
+      this.selectedRole = ''
+      this.userDepartModel = { userId: '', departIdList: [] }
+      this.checkedDepartNames = []
+      this.checkedDepartNameString = ''
+      this.checkedDepartKeys = []
+      this.selectedDepartKeys = []
       this.picUrl = ''
       this.refresh()
       this.edit({ activitiSync: '1' })
@@ -377,10 +384,11 @@ export default {
     moment,
     handleSubmit() {
       const that = this
+      that.confirmLoading = true
       // 触发表单验证
       this.form.validateFields((err, values) => {
         if (!err) {
-          that.confirmLoading = true
+          
           let avatar = that.model.avatar
           if (!values.birthday) {
             values.birthday = ''
@@ -408,17 +416,20 @@ export default {
               if (res.success) {
                 that.$message.success(res.message)
                 that.$emit('ok')
-                that.close()
+                // that.close()
+                that.visible = false
+                that.confirmLoading = false
               } else {
                 that.$message.warning(res.message)
               }
             })
             .finally(() => {
-              that.confirmLoading = false
-              that.checkedDepartNames = []
-              that.userDepartModel.departIdList = { userId: '', departIdList: [] }
-              that.close()
+              
+             
+              
             })
+        }else{
+          that.confirmLoading = false
         }
       })
     },

+ 1 - 1
vue.config.js

@@ -74,7 +74,7 @@ module.exports = {
         // target: 'http://192.168.1.188:8088', //请求本地 需要jeecg-boot后台项目  英豪
         // target: 'http://192.168.2.115:8080', //请求本地 需要jeecg-boot后台项目  祚云
         // target: 'http://192.168.1.43:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
-        // target: 'http://192.168.1.43:8088', //请求本地 需要jeecg-boot后台项目  毕洁泉
+        target: 'http://192.168.1.43:8088', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.1.43:8087', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.0.252:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.1.219:8080', //请求本地 需要jeecg-boot后台项目  赵西安