syh 5 anni fa
parent
commit
f7d7c0c9b6

+ 3 - 0
src/views/modules/Statistics/components/timeCheck.vue

@@ -146,6 +146,9 @@ export default {
     },
     getAdd(checked) {
       this.active = checked
+      if(checked!=9){
+          this.startValue = []
+      }
       active = checked
       this.$emit('update:startValue', this.startValue)
       this.$emit('getAdd', checked)

+ 540 - 0
src/views/modules/Statistics/toutiaoAccount.vue

@@ -0,0 +1,540 @@
+<style lang="scss" scoped>
+  .search-bar {
+    display: flex;
+    align-items: center;
+  }
+
+  .search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+  }
+</style>
+<style>
+  .search-box .ant-card-body {
+    padding: 5px 15px;
+  }
+
+  .ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+  }
+
+  .yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+  }
+
+  .ant-table-thead div {
+    font-weight: 700;
+  }
+
+  .tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+  }
+
+  th div {
+    white-space: nowrap;
+  }
+</style>
+<template>
+  <div class="data-account-statistics">
+    <a-row class="image-list-heading vm-panel">
+      <div class="panel-heading" style="display:flex;justify-content: space-between;">
+        {{ title }}
+        <a-button @click="dianji">进入素材报表</a-button>
+      </div>
+      <a-row type="flex" align="middle" justify="space-between" class="panel-body">
+        <div class="search-bar" style="width:100%">
+          <span>账户选择:</span>
+          <treeselect :appId.sync="appId" />
+          <a-button type="primary" style="margin:10px" @click="addUser">搜索</a-button>
+          <a-button type="primary" icon="reload" @click="getDataReset"
+            style="background-color:#67c23a;border-color:#67c23a">刷新</a-button>
+          <a-button type="primary" style="margin:10px" @click="getDataResetAll">重置</a-button>
+        </div>
+      </a-row>
+      <a-row>
+        <a-col :span="24">
+          <a-card :bordered="false" class="search-box">
+            <time-check @getAdd="getAdd" :startValue.sync="startValue" :timeList="timeList" ref="timeCheck">
+            </time-check>
+          </a-card>
+        </a-col>
+      </a-row>
+    </a-row>
+    <a-row :gutter="10" style="margin-top:10px">
+      <a-col :span="24">
+        <a-card style="width:100%;">
+          <a-table :columns="columns" :dataSource="data" bordered id="outTable" :pagination="ipagination" size="middle"
+            :customRow="rowClick" :loading="loading" :scroll="{ x: true }">
+            <div slot="url" slot-scope="url">
+              <video class="video" :src="url" controls="controls" style="height:200px;width:112.5px">
+                您的浏览器不支持 video 标签。
+              </video>
+            </div>
+            <!-- <span slot="photoClickRatio" slot-scope="photoClickRatio">{{ photoClickRatio | getBo }}</span>
+            <span slot="actionRatio" slot-scope="actionRatio">{{ actionRatio | getBo }}</span>
+            <span slot="impression1kCost" slot-scope="impression1kCost">{{ impression1kCost | toFixtwo }}</span>
+            <span slot="photoClickCost" slot-scope="photoClickCost">{{ photoClickCost | toFixtwo }}</span>
+            <span slot="actionCost" slot-scope="actionCost">{{ actionCost | toFixtwo }}</span>
+            <span slot="conversionPrice" slot-scope="conversionPrice">{{ conversionPrice | toFixtwo }}</span> -->
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+    <ratio-modal ref="ratio" />
+  </div>
+</template>
+
+<script>
+  import ARow from 'ant-design-vue/es/grid/Row'
+  import ACol from 'ant-design-vue/es/grid/Col'
+  import countTo from 'vue-count-to'
+  import moment from 'moment'
+  import {
+    getMaterialReportByAccount
+  } from '@api/statistics'
+  import {
+    getAction,
+    postAction,
+    postFile,
+    downFile,
+    downFilePost,
+    deleteAction
+  } from '@/api/manage'
+  import axios from 'axios'
+  import lifting from './components/lifting'
+  import timeCheck from './components/timeCheck'
+  import ratioModal from './components/ratioModal'
+  import {
+    mapGetters
+  } from 'vuex'
+
+  import {
+    JeecgListMixin
+  } from '@/mixins/ipagination'
+
+  // import the component
+  import Treeselect from './components/Treeselect.vue'
+
+  // 引入基本模板
+  let echarts = require('echarts/lib/echarts')
+  // 引入柱状图组件
+  require('echarts/lib/chart/bar')
+  require('echarts/lib/chart/pie')
+  require('echarts/lib/chart/line')
+  // 引入提示框和title组件
+  require('echarts/lib/component/tooltip')
+  require('echarts/lib/component/title')
+  require('echarts/lib/component/graphic')
+  require('echarts/lib/component/toolbox')
+  require('echarts/lib/component/legend')
+  var length = 0
+  var active = 1
+
+  const columns = [{
+      title: '视频',
+      dataIndex: 'videoUrl',
+      key: 'videoUrl',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'videoUrl'
+      }
+    },
+    {
+      title: '花费',
+      dataIndex: 'cost',
+      key: 'cost',
+      align: 'center',
+      sorter: (a, b) => a.cost - b.cost
+    },
+    {
+      title: '展示量',
+      dataIndex: 'showNum',
+      key: 'showNum',
+      align: 'center',
+      sorter: (a, b) => a.showNum - b.showNum
+    },
+    {
+      title: '点击量',
+      dataIndex: 'click',
+      key: 'click',
+      align: 'center',
+      sorter: (a, b) => a.click - b.click
+    },
+    {
+      title: '转化量',
+      dataIndex: 'convertNum',
+      key: 'convertNum',
+      align: 'center',
+      sorter: (a, b) => a.convertNum - b.convertNum
+    },
+    {
+      title: '应用下载-激活',
+      dataIndex: 'active',
+      key: 'active',
+      align: 'center',
+      sorter: (a, b) => a.active - b.active
+    },
+    {
+      title: '应用下载-安卓下载完成',
+      dataIndex: 'downloadFinish',
+      key: 'downloadFinish',
+      align: 'center',
+      sorter: (a, b) => a.downloadFinish - b.downloadFinish
+    },
+    {
+      title: '应用下载-点击安装数',
+      dataIndex: 'clickInstall',
+      key: 'clickInstall',
+      align: 'center',
+      sorter: (a, b) => a.clickInstall - b.clickInstall
+    },
+    {
+      title: '应用下载-付费',
+      dataIndex: 'inAppPay',
+      key: 'inAppPay',
+      align: 'center',
+      sorter: (a, b) => a.inAppPay - b.inAppPay
+    },
+    {
+      title: '总播放',
+      dataIndex: 'totalPlay',
+      key: 'totalPlay',
+      align: 'center',
+      sorter: (a, b) => a.totalPlay - b.totalPlay
+    },
+    {
+      title: '有效播放',
+      dataIndex: 'validPlay',
+      key: 'validPlay',
+      align: 'center',
+      sorter: (a, b) => a.validPlay - b.validPlay
+    },
+    {
+      title: 'wifi播放',
+      dataIndex: 'wifiPlay',
+      key: 'wifiPlay',
+      align: 'center',
+      sorter: (a, b) => a.wifiPlay - b.wifiPlay
+    },
+    {
+      title: '播放100%进度总数',
+      dataIndex: 'play100FeedBreak',
+      key: 'play100FeedBreak',
+      align: 'center',
+      sorter: (a, b) => a.play100FeedBreak - b.play100FeedBreak
+    },
+    {
+      title: '播放75%进度总数',
+      dataIndex: 'play75FeedBreak',
+      key: 'play75FeedBreak',
+      align: 'center',
+      sorter: (a, b) => a.play75FeedBreak - b.play75FeedBreak
+    },
+    {
+      title: '评论数',
+      dataIndex: 'comment',
+      key: 'comment',
+      align: 'center',
+      sorter: (a, b) => a.comment - b.comment
+    },
+    {
+      title: '平均次留数',
+      dataIndex: 'nextDayOpen',
+      key: 'nextDayOpen',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpen - b.nextDayOpen
+    },
+    {
+      title: '平均次留率(%)',
+      dataIndex: 'nextDayOpenRate',
+      key: 'nextDayOpenRate',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpenRate - b.nextDayOpenRate
+    },
+    {
+      title: '平均次留成本(元)',
+      dataIndex: 'nextDayOpenCost',
+      key: 'nextDayOpenCost',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpenCost - b.nextDayOpenCost
+    }
+  ]
+  const columnsDetail = [{
+      title: '日期',
+      dataIndex: 'statDate',
+      key: 'statDate',
+      align: 'center'
+    },
+    {
+      title: '花费',
+      dataIndex: 'cost',
+      key: 'cost',
+      align: 'center'
+    },
+    {
+      title: '封面曝光数',
+      dataIndex: 'photoShow',
+      key: 'photoShow',
+      align: 'center'
+    },
+    {
+      title: '封面点击数',
+      dataIndex: 'photoClick',
+      key: 'photoClick',
+      align: 'center'
+    },
+    {
+      title: '素材曝光数',
+      dataIndex: 'aclick',
+      key: 'aclick',
+      align: 'center'
+    },
+    {
+      title: '行为数',
+      dataIndex: 'bclick',
+      key: 'bclick',
+      align: 'center'
+    },
+    {
+      title: '封面点击率',
+      dataIndex: 'photoClickRatio',
+      key: 'photoClickRatio',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'photoClickRatio'
+      }
+    },
+    {
+      title: '行为率',
+      dataIndex: 'actionRatio',
+      key: 'actionRatio',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'actionRatio'
+      }
+    },
+
+    {
+      title: '均千次封面曝光花费(元)',
+      dataIndex: 'impression1kCost',
+      key: 'impression1kCost',
+      scopedSlots: {
+        customRender: 'impression1kCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '平均封面点击单价(元)',
+      dataIndex: 'photoClickCost',
+      key: 'photoClickCost',
+      scopedSlots: {
+        customRender: 'photoClickCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '平均行为单价(元)',
+      dataIndex: 'actionCost',
+      key: 'actionCost',
+      scopedSlots: {
+        customRender: 'actionCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '转化数',
+      dataIndex: 'conversions',
+      key: 'conversions',
+      align: 'center'
+    },
+    {
+      title: '转化单价(元)',
+      dataIndex: 'conversionPrice',
+      key: 'conversionPrice',
+      scopedSlots: {
+        customRender: 'conversionPrice'
+      },
+      align: 'center'
+    }
+  ]
+  export default {
+    name: 'data-display-statistics',
+    components: {
+      ACol,
+      ARow,
+      countTo,
+      lifting,
+      timeCheck,
+      ratioModal,
+      Treeselect
+    },
+    mixins: [JeecgListMixin],
+    data: function () {
+      return {
+        title: '头条账户素材报表',
+        show: true,
+        timeList: [],
+        active: 1,
+        data: [],
+        columns,
+        columnsDetail,
+        list: [],
+        appId: [],
+        startValue: [],
+        allValue: [],
+        loading: false,
+        rowClick: record => ({
+          // 事件
+          on: {
+            click: () => {
+              // 点击改行时要做的事情
+              // this.detail = record
+              // this.visible = true
+              // this.getMineList(record.signature)
+              this.$refs.ratio.getMineList(record, this.active)
+            }
+          }
+        })
+      }
+    },
+    filters: {
+      formatDate: function (value) {
+        let date = new Date(value)
+        let y = date.getFullYear()
+        let MM = date.getMonth() + 1
+        MM = MM < 10 ? '0' + MM : MM
+        let d = date.getDate()
+        d = d < 10 ? '0' + d : d
+        let h = date.getHours()
+        h = h < 10 ? '0' + h : h
+        let m = date.getMinutes()
+        m = m < 10 ? '0' + m : m
+        let s = date.getSeconds()
+        s = s < 10 ? '0' + s : s
+        return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
+      },
+      toFixtwo: function (value) {
+        if (value) {
+          return value.toFixed(2)
+        } else {
+          return 0.0
+        }
+      },
+      getBo: function (value) {
+        if (value) {
+          return (value * 100).toFixed(2) + '%'
+        } else {
+          return '0.00%'
+        }
+      }
+    },
+    methods: {
+      moment,
+      ...mapGetters(['nickname', 'avatar', 'userInfo']),
+      disabledDate(current) {
+        return current && current > moment().endOf('day')
+      },
+      handleChange(value) {
+        console.log(value)
+        //   this.appId = value
+      },
+      getElseData(value) {
+        this.getStatistics()
+      },
+      handleBlur() {
+        console.log('blur')
+      },
+      getDataReset() {
+        this.active = 1
+        this.allValue = []
+        this.addUser()
+      },
+      getDataResetAll() {
+        this.active = 1
+        this.$refs.timeCheck.getAdd(1)
+        this.allValue = []
+        this.appId = []
+        this.data = []
+      },
+      addUser() {
+        this.loading = true
+        var that = this
+        if (this.appId.length > 0) {
+          var params = {}
+          params.accountIds = JSON.stringify(that.appId)
+          params.type = that.active
+          if (that.active == 9) {
+            params.startDate = this.allValue[0]
+            params.endDate = this.allValue[1]
+            params.userId = this.userInfo().id
+            postAction('/ctop/bytedanceCreativeDailyReport/bytedanceCreativeDailyReportList', params).then(res => {
+              if (res.success) {
+                if (res.result.length > 0) {
+                  this.data = res.result
+                  this.ipagination.total = res.result.length
+                } else {
+                  this.$message.error('选择的账户无数据')
+                }
+                this.loading = false
+              } else {
+                this.$message.error(res.message)
+                this.loading = false
+              }
+            })
+          }else{
+             this.$message.error('请选择时间段') 
+          }
+        } else {
+          this.$message.error('请选择账户以及时间')
+          return
+        }
+
+      },
+      getStatistics() {
+        var params = {}
+        params.accountIds = JSON.stringify(this.appId)
+        params.type = this.active
+        params.statHour = this.statHour
+        params.discount = this.discount
+        if (this.active == 9) {
+          params.startDate = this.allValue[0]
+          params.endDate = this.allValue[1]
+        }
+        this.data = []
+      },
+      getAdd(checked) {
+        if (checked == 9) {
+          if (this.startValue.length > 0 && this.startValue[0]) {
+            this.allValue[0] = moment(this.startValue[0]._d).format('YYYY-MM-DD')
+            this.allValue[1] = moment(this.startValue[1]._d).format('YYYY-MM-DD')
+          }
+        } else {
+          this.startValue = []
+          this.allValue = []
+        }
+        this.active = checked
+        active = checked
+        this.ipagination.current = 1
+      },
+      dianji() {
+        this.$router.replace({
+          path: '/Statistics/toutiaoMaterialStatistics'
+        })
+      }
+    },
+    watch: {},
+    distoryed() {},
+    mounted: function () {
+      this.$nextTick(() => {})
+    }
+  }
+</script>

+ 537 - 0
src/views/modules/Statistics/toutiaoMaterialStatistics.vue

@@ -0,0 +1,537 @@
+<style lang="scss" scoped>
+  .search-bar {
+    display: flex;
+    align-items: center;
+  }
+
+  .search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+  }
+</style>
+<style>
+  /* .data-display-statistics .ant-card-body {
+  padding: 0 15px;
+} */
+  .toutiao-material-statistics .search-box .ant-card-body {
+    display: flex;
+  }
+
+  .data-display-statistics .ant-col-6 {
+    margin: 10px 0;
+  }
+
+  .data-display-statistics .ant-col-6 .ant-card-body {
+    display: flex;
+    justify-content: center;
+  }
+
+  .data-display-statistics .ant-col-6 p,
+  .data-display-statistics .ant-col-6 span {
+    text-align: center;
+    line-height: 40px;
+    font-size: 30px;
+    font-weight: 600;
+    color: red;
+    margin: 0;
+  }
+
+  .search-box .ant-card-body {
+    padding: 5px 15px;
+  }
+
+  .data-display-statistics .ant-col-6 .ant-card-body .styleElse {
+    line-height: 60px;
+    height: 40px;
+    font-size: 16px;
+    font-weight: 400;
+    margin-left: 10px;
+  }
+
+  .ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+  }
+
+  .yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+  }
+
+  .ant-table-thead div {
+    font-weight: 700;
+  }
+
+  .tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+  }
+
+  .ant-table-thead tr th {
+    background: none;
+  }
+
+  /* th div {
+  white-space: nowrap;
+} */
+</style>
+<template>
+  <div class="toutiao-material-statistics">
+    <a-row class="image-list-heading vm-panel">
+      <div class="panel-heading" style="display:flex;justify-content: space-between;">
+        {{ title }}
+        <a-button @click="dianji">进入账户报表</a-button>
+      </div>
+      <a-row>
+        <a-col :span="24">
+          <a-card :bordered="false" class="search-box" style="display:flex">
+            <time-check @getAdd="getAdd" :startValue.sync="startValue" :timeList="timeList" ref="timeCheck">
+            </time-check>
+            <a-button type="primary" style="margin-left:10px" @click="getList">搜索</a-button>
+            <a-button type="primary" style="margin-left:10px" @click="getDataResetAll">重置</a-button>
+          </a-card>
+        </a-col>
+      </a-row>
+    </a-row>
+    <a-row :gutter="10" style="margin-top:10px">
+      <a-col :span="24">
+        <a-card style="width:100%;">
+          <a-table :columns="columns" :dataSource="data" bordered id="outTable" :pagination="ipagination" size="middle"
+            :customRow="rowClick" :loading="loading" :scroll="{ x: 1900 }">
+            <div slot="videoUrl" slot-scope="videoUrl">
+              <video @click.stop class="video" :src="videoUrl" controls="controls" style="height:200px;width:112.5px">
+                您的浏览器不支持 video 标签。
+              </video>
+            </div>
+            <!-- <span slot="photoClickRatio" slot-scope="photoClickRatio">{{ photoClickRatio | getBo }}</span>
+            <span slot="actionRatio" slot-scope="actionRatio">{{ actionRatio | getBo }}</span>
+            <span slot="impression1kCost" slot-scope="impression1kCost">{{ impression1kCost | toFixtwo }}</span>
+            <span slot="photoClickCost" slot-scope="photoClickCost">{{ photoClickCost | toFixtwo }}</span>
+            <span slot="actionCost" slot-scope="actionCost">{{ actionCost | toFixtwo }}</span>
+            <span slot="conversionPrice" slot-scope="conversionPrice">{{ conversionPrice | toFixtwo }}</span> -->
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+
+    <ratio-modal ref="ratio" />
+  </div>
+</template>
+
+<script>
+  import ARow from 'ant-design-vue/es/grid/Row'
+  import ACol from 'ant-design-vue/es/grid/Col'
+  import moment from 'moment'
+  import {
+    getKuaiShouMaterialMarket,
+    getKuaiShouChainRatio
+  } from '@api/statistics'
+
+  import {
+    getAction,
+    postAction,
+    postFile,
+    downFile,
+    downFilePost,
+    deleteAction
+  } from '@/api/manage'
+  import axios from 'axios'
+  import {
+    mapGetters
+  } from 'vuex'
+  import {
+    stopOtherVideo,
+    closeAllVideoFun
+  } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
+
+  import timeCheck from './components/timeCheck'
+  import ratioModal from './components/ratioModal'
+
+  import {
+    JeecgListMixin
+  } from '@/mixins/ipagination'
+
+  var length = 0
+  var active = 1
+  const columns = [{
+      title: '视频',
+      dataIndex: 'videoUrl',
+      key: 'videoUrl',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'videoUrl'
+      }
+    },
+    {
+      title: '花费',
+      dataIndex: 'cost',
+      key: 'cost',
+      align: 'center',
+      sorter: (a, b) => a.cost - b.cost
+    },
+    {
+      title: '展示量',
+      dataIndex: 'showNum',
+      key: 'showNum',
+      align: 'center',
+      sorter: (a, b) => a.showNum - b.showNum
+    },
+    {
+      title: '点击量',
+      dataIndex: 'click',
+      key: 'click',
+      align: 'center',
+      sorter: (a, b) => a.click - b.click
+    },
+    {
+      title: '转化量',
+      dataIndex: 'convertNum',
+      key: 'convertNum',
+      align: 'center',
+      sorter: (a, b) => a.convertNum - b.convertNum
+    },
+    {
+      title: '应用下载-激活',
+      dataIndex: 'active',
+      key: 'active',
+      align: 'center',
+      sorter: (a, b) => a.active - b.active
+    },
+    {
+      title: '应用下载-安卓下载完成',
+      dataIndex: 'downloadFinish',
+      key: 'downloadFinish',
+      align: 'center',
+      sorter: (a, b) => a.downloadFinish - b.downloadFinish
+    },
+    {
+      title: '应用下载-点击安装数',
+      dataIndex: 'clickInstall',
+      key: 'clickInstall',
+      align: 'center',
+      sorter: (a, b) => a.clickInstall - b.clickInstall
+    },
+    {
+      title: '应用下载-付费',
+      dataIndex: 'inAppPay',
+      key: 'inAppPay',
+      align: 'center',
+      sorter: (a, b) => a.inAppPay - b.inAppPay
+    },
+    {
+      title: '总播放',
+      dataIndex: 'totalPlay',
+      key: 'totalPlay',
+      align: 'center',
+      sorter: (a, b) => a.totalPlay - b.totalPlay
+    },
+    {
+      title: '有效播放',
+      dataIndex: 'validPlay',
+      key: 'validPlay',
+      align: 'center',
+      sorter: (a, b) => a.validPlay - b.validPlay
+    },
+    {
+      title: 'wifi播放',
+      dataIndex: 'wifiPlay',
+      key: 'wifiPlay',
+      align: 'center',
+      sorter: (a, b) => a.wifiPlay - b.wifiPlay
+    },
+    {
+      title: '播放100%进度总数',
+      dataIndex: 'play100FeedBreak',
+      key: 'play100FeedBreak',
+      align: 'center',
+      sorter: (a, b) => a.play100FeedBreak - b.play100FeedBreak
+    },
+    {
+      title: '播放75%进度总数',
+      dataIndex: 'play75FeedBreak',
+      key: 'play75FeedBreak',
+      align: 'center',
+      sorter: (a, b) => a.play75FeedBreak - b.play75FeedBreak
+    },
+    {
+      title: '评论数',
+      dataIndex: 'comment',
+      key: 'comment',
+      align: 'center',
+      sorter: (a, b) => a.comment - b.comment
+    },
+    {
+      title: '平均次留数',
+      dataIndex: 'nextDayOpen',
+      key: 'nextDayOpen',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpen - b.nextDayOpen
+    },
+    {
+      title: '平均次留率(%)',
+      dataIndex: 'nextDayOpenRate',
+      key: 'nextDayOpenRate',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpenRate - b.nextDayOpenRate
+    },
+    {
+      title: '平均次留成本(元)',
+      dataIndex: 'nextDayOpenCost',
+      key: 'nextDayOpenCost',
+      align: 'center',
+      sorter: (a, b) => a.nextDayOpenCost - b.nextDayOpenCost
+    }
+  ]
+  const columnsDetail = [{
+      title: '日期',
+      dataIndex: 'statDate',
+      key: 'statDate',
+      align: 'center'
+    },
+    {
+      title: '花费',
+      dataIndex: 'cost',
+      key: 'cost',
+      align: 'center'
+    },
+    {
+      title: '封面曝光数',
+      dataIndex: 'photoShow',
+      key: 'photoShow',
+      align: 'center'
+    },
+    {
+      title: '封面点击数',
+      dataIndex: 'photoClick',
+      key: 'photoClick',
+      align: 'center'
+    },
+    {
+      title: '素材曝光数',
+      dataIndex: 'aclick',
+      key: 'aclick',
+      align: 'center'
+    },
+    {
+      title: '行为数',
+      dataIndex: 'bclick',
+      key: 'bclick',
+      align: 'center'
+    },
+    {
+      title: '封面点击率',
+      dataIndex: 'photoClickRatio',
+      key: 'photoClickRatio',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'photoClickRatio'
+      }
+    },
+    {
+      title: '行为率',
+      dataIndex: 'actionRatio',
+      key: 'actionRatio',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'actionRatio'
+      }
+    },
+
+    {
+      title: '均千次封面曝光花费(元)',
+      dataIndex: 'impression1kCost',
+      key: 'impression1kCost',
+      scopedSlots: {
+        customRender: 'impression1kCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '平均封面点击单价(元)',
+      dataIndex: 'photoClickCost',
+      key: 'photoClickCost',
+      scopedSlots: {
+        customRender: 'photoClickCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '平均行为单价(元)',
+      dataIndex: 'actionCost',
+      key: 'actionCost',
+      scopedSlots: {
+        customRender: 'actionCost'
+      },
+      align: 'center'
+    },
+    {
+      title: '转化数',
+      dataIndex: 'conversions',
+      key: 'conversions',
+      align: 'center'
+    },
+    {
+      title: '转化单价(元)',
+      dataIndex: 'conversionPrice',
+      key: 'conversionPrice',
+      scopedSlots: {
+        customRender: 'conversionPrice'
+      },
+      align: 'center'
+    }
+  ]
+  export default {
+    name: 'data-display-statistics',
+    components: {
+      ACol,
+      ARow,
+      timeCheck,
+      ratioModal
+    },
+    mixins: [JeecgListMixin],
+    data: function () {
+      return {
+        title: '头条素材大盘报表',
+        columns,
+        columnsDetail,
+        timeList: [],
+        data: [],
+        active: 1,
+        pagin: 1,
+        allValue: [],
+        startValue: [],
+        visible: false,
+        showVideo: false,
+        detail: null,
+        dataDetail: [],
+        dataYestodayDetail: [],
+        dataChainRatio: [],
+        loading: false,
+        rowClick: record => ({
+          // 事件
+          on: {
+            click: () => {
+              // 点击改行时要做的事情
+              // this.detail = record
+              // this.visible = true
+              // this.getMineList(record.signature)
+              this.$refs.ratio.getMineList(record, this.active)
+            }
+          }
+        })
+      }
+    },
+    filters: {
+      formatDate: function (value) {
+        let date = new Date(value)
+        let y = date.getFullYear()
+        let MM = date.getMonth() + 1
+        MM = MM < 10 ? '0' + MM : MM
+        let d = date.getDate()
+        d = d < 10 ? '0' + d : d
+        let h = date.getHours()
+        h = h < 10 ? '0' + h : h
+        let m = date.getMinutes()
+        m = m < 10 ? '0' + m : m
+        let s = date.getSeconds()
+        s = s < 10 ? '0' + s : s
+        return y + '-' + MM + '-' + d + ' ' + h + ':' + m + ':' + s
+      },
+      toFixtwo: function (value) {
+        if (value) {
+          return value.toFixed(2)
+        } else {
+          return 0.0
+        }
+      },
+      getBo: function (value) {
+        if (value) {
+          return (value * 100).toFixed(2) + '%'
+        } else {
+          return '0.00%'
+        }
+      }
+    },
+    methods: {
+      handleOk() {
+        this.visible = false
+      },
+      ...mapGetters(['nickname', 'avatar', 'userInfo']),
+      moment,
+      disabledDate(current) {
+        return current && current > moment().endOf('day')
+      },
+      getAdd(checked) {
+        if (checked == 9) {
+          if (this.startValue.length > 0 && this.startValue[0]) {
+            this.allValue[1] = moment(this.startValue[1]._d).format('YYYY-MM-DD')
+            this.allValue[0] = moment(this.startValue[0]._d).format('YYYY-MM-DD')
+          }
+        } else {
+          this.startValue = []
+          this.allValue = []
+        }
+        this.active = checked
+        active = checked
+        this.ipagination.current = 1
+        // this.getList()
+      },
+      getDataResetAll() {
+        this.startValue = []
+        this.allValue = []
+        this.$refs.timeCheck.getAdd(1)
+        this.data = []
+      },
+      getList() {
+        if (this.startValue.length > 0 && this.startValue[0]) {
+          this.data = []
+          this.loading = true
+          var params = {}
+          if (this.active == 9) {
+            params.startDate = this.allValue[0]
+            params.endDate = this.allValue[1]
+            params.userId = this.userInfo().id
+            // params.userId="8a6e8536c5794799b5a78e8dbe995a13"
+          }
+          postAction('/ctop/bytedanceCreativeDailyReport/bytedanceCreativeDailyReportList', params).then(res => {
+            if (res.success) {
+              this.data = res.result.map((item, index) => {
+                return {
+                  key: index,
+                  ...item
+                }
+              })
+              this.loading = false
+              this.ipagination.total = res.result.length
+            } else {
+              this.$message.error(res.message)
+              this.loading = false
+            }
+          })
+        } else {
+          this.$message.error('请选择时间段')
+        }
+
+      },
+      dianji() {
+        this.$router.replace({
+          path: '/Statistics/toutiaoAccountMaterStatistics'
+        })
+      }
+    },
+    watch: {},
+    distoryed() {},
+    updated() {
+      stopOtherVideo()
+    },
+    mounted: function () {
+      this.$nextTick(() => {})
+    }
+  }
+</script>

+ 141 - 0
src/views/modules/achievements/adminDetail.vue

@@ -0,0 +1,141 @@
+<style>
+</style>
+<template>
+  <div class="admin-detail">
+    <a-row :gutter="10" style="margin-top:10px">
+      <a-col :span="24">
+        <a-card style="width:100%;">
+          <a-table :columns="columns" :dataSource="dataList" bordered :loading="loading" size="middle"
+            :pagination="false">
+            <span slot-scope="text" slot="url">
+              <video class="video" :src="text" controls="controls" style="height:200px">
+                您的浏览器不支持 video 标签。
+              </video>
+            </span>
+
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+  </div>
+</template>
+
+<script>
+  import ChartCard from '@/components/ChartCard'
+  import ACol from 'ant-design-vue/es/grid/Col'
+  import ATooltip from 'ant-design-vue/es/tooltip/Tooltip'
+  import MiniArea from '@/components/chart/MiniArea'
+  import MiniBar from '@/components/chart/MiniBar'
+  import MiniProgress from '@/components/chart/MiniProgress'
+  import RankList from '@/components/chart/RankList'
+  import Bar from '@/components/chart/Bar'
+  import LineChartMultid from '@/components/chart/LineChartMultid'
+  import HeadInfo from '@/components/tools/HeadInfo.vue'
+
+  import Trend from '@/components/Trend'
+
+  import {
+    getAction,
+    postAction
+  } from '@/api/manage'
+  import {
+    mapGetters
+  } from 'vuex'
+
+  import qs from 'qs'
+
+  const barData = []
+  for (let i = 0; i < 12; i += 1) {
+    barData.push({
+      x: `${i + 1}月`,
+      y: Math.floor(Math.random() * 1000) + 200
+    })
+  }
+
+  const columns = [{
+      title: '视频',
+      dataIndex: 'url',
+      key: 'url',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'url'
+      },
+      width: 200
+    },
+    {
+      title: '素材名称',
+      dataIndex: 'materialName',
+      key: 'materialName',
+      align: 'center'
+    },
+    {
+      title: '水印素材名称',
+      dataIndex: 'watermarkMaterialName',
+      key: 'watermarkMaterialName',
+      align: 'center'
+    },
+    {
+      title: 'md5',
+      dataIndex: 'code',
+      key: 'code',
+      align: 'center'
+    },
+  ]
+
+  export default {
+    name: 'admin-info',
+    components: {
+      ATooltip,
+      ACol,
+    },
+
+    data: function () {
+      return {
+        title: '工作台',
+        loginfo: {},
+        barData,
+        visitInfo: [],
+        visitFields: ['ip', 'visit'],
+        loading: false,
+        rankList: [],
+        tabListNoTitle: [{
+            key: 'kuaishou',
+            tab: '快手'
+          },
+          {
+            key: 'toutiao',
+            tab: '头条'
+          }
+        ],
+        noTitleKey: 'kuaishou',
+        a: '',
+        columns,
+        dataList: [],
+      }
+    },
+    methods: {
+      ...mapGetters(['nickname', 'avatar', 'userInfo']),
+    },
+    created() {
+      var userId = localStorage.getItem('detailUserId')
+      var appType = localStorage.getItem('appType') == 'kuaishou' ? 2 : 1
+      postAction('/ctop/performance2/getEffiVideoList', {
+        "year": 2019,
+        "quarter": 4,
+        "userId": userId,
+        "appType": appType
+      }).then(res => {
+        if (res.success) {
+          this.dataList = res.result.map((item, index) => {
+            return {
+              ...item,
+              key: index,
+            }
+          })
+        } else {
+          this.$message.error(res.message)
+        }
+      })
+    }
+  }
+</script>

+ 191 - 0
src/views/modules/achievements/adminInfo.vue

@@ -0,0 +1,191 @@
+<style>
+  .admin-info .ant-list-item-content {
+    display: flex;
+    justify-content: space-around;
+  }
+
+  .admin-info .ant-table-middle tr.ant-table-expanded-row td>.ant-table-wrapper {
+    margin: -12px -9px -13px;
+  }
+</style>
+<template>
+  <div class="admin-info">
+    <a-row :gutter="10" style="margin-top:10px">
+      <a-col :span="24">
+        <a-card style="width:100%;" :tabList="tabListNoTitle" :activeTabKey="noTitleKey"
+          @tabChange="key => onTabChange(key, 'noTitleKey')">
+          <a-table :columns="columns" :dataSource="dataList" bordered :loading="loading" size="middle"
+            :pagination="false">
+            <span slot-scope="text" slot="videoUrl">
+              <video class="video" :src="text" controls="controls" style="height:200px">
+                您的浏览器不支持 video 标签。
+              </video>
+            </span>
+            <span slot="action" slot-scope="text,record">
+              <a :disabled="record.effiVideoCount == 0" @click="toDetail(record)">查看详情</a>
+            </span>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+  </div>
+</template>
+
+<script>
+  import ChartCard from '@/components/ChartCard'
+  import ACol from 'ant-design-vue/es/grid/Col'
+  import ATooltip from 'ant-design-vue/es/tooltip/Tooltip'
+  import MiniArea from '@/components/chart/MiniArea'
+  import MiniBar from '@/components/chart/MiniBar'
+  import MiniProgress from '@/components/chart/MiniProgress'
+  import RankList from '@/components/chart/RankList'
+  import Bar from '@/components/chart/Bar'
+  import LineChartMultid from '@/components/chart/LineChartMultid'
+  import HeadInfo from '@/components/tools/HeadInfo.vue'
+
+  import Trend from '@/components/Trend'
+
+  import {
+    getAction,
+    postAction
+  } from '@/api/manage'
+  import {
+    mapGetters
+  } from 'vuex'
+
+  import qs from 'qs'
+
+  const barData = []
+  for (let i = 0; i < 12; i += 1) {
+    barData.push({
+      x: `${i + 1}月`,
+      y: Math.floor(Math.random() * 1000) + 200
+    })
+  }
+
+  const columns = [{
+      title: '姓名',
+      dataIndex: 'realname',
+      key: 'realname',
+      align: 'center',
+      width: 200
+    },
+    {
+      title: '角色',
+      dataIndex: 'roleName',
+      key: 'roleName',
+      align: 'center'
+    },
+    {
+      title: '有效视频数量',
+      dataIndex: 'effiVideoCount',
+      key: 'effiVideoCount',
+      align: 'center'
+    },
+    {
+      title: '总视频数量',
+      dataIndex: 'videoCount',
+      key: 'videoCount',
+      align: 'center'
+    },
+    {
+      title: '消耗',
+      dataIndex: 'cost',
+      key: 'cost',
+      align: 'center'
+    },
+    {
+      title: '操作',
+      dataIndex: 'action',
+      key: 'action',
+      align: 'center',
+      scopedSlots: {
+        customRender: 'action'
+      },
+    },
+  ]
+
+  export default {
+    name: 'admin-info',
+    components: {
+      ATooltip,
+      ACol,
+    },
+
+    data: function () {
+      return {
+        title: '工作台',
+        loginfo: {},
+        barData,
+        visitInfo: [],
+        visitFields: ['ip', 'visit'],
+        loading: false,
+        rankList: [],
+        tabListNoTitle: [{
+            key: 'kuaishou',
+            tab: '快手'
+          },
+          {
+            key: 'toutiao',
+            tab: '头条'
+          }
+        ],
+        noTitleKey: 'kuaishou',
+        a: '',
+        columns,
+        dataList: [],
+      }
+    },
+    methods: {
+      ...mapGetters(['nickname', 'avatar', 'userInfo']),
+      onTabChange(key, type) {
+        console.log(key, type)
+        this[type] = key
+        if (key == 'kuaishou') {
+          this.getKuaishouList()
+        } else if (key == 'toutiao') {
+          this.getToutiaoList()
+        }
+      },
+      toDetail(item) {
+          localStorage.setItem('detailUserId',item.userId)
+          localStorage.setItem('appType',this.noTitleKey)
+          this.$router.replace({ path: '/achievements/adminDetail' })
+      },
+      getKuaishouList() {
+        postAction('/ctop/performance2/kuaishouPerformanceInfoNow', '').then(res => {
+          console.log(res)
+          if (res.success) {
+            this.dataList = res.result.map((item, index) => {
+              return {
+                ...item,
+                key: index,
+              }
+            })
+          } else {
+            this.$message.error(res.message)
+          }
+        })
+      },
+
+      getToutiaoList() {
+        postAction('/ctop/performance2/toutiaoPerformanceInfoNow', '').then(res => {
+          console.log(res)
+          if (res.success) {
+            this.dataList = res.result.map((item, index) => {
+              return {
+                ...item,
+                key: index,
+              }
+            })
+          } else {
+            this.$message.error(res.message)
+          }
+        })
+      }
+    },
+    created() {
+      this.getKuaishouList()
+    }
+  }
+</script>

+ 8 - 0
src/views/modules/advertiser/ProjectList.vue

@@ -54,6 +54,8 @@
         @change="handleTableChange"
       >
         <span slot="maxBid" slot-scope="text">{{ text / 1000 }}</span>
+        <span slot="maxDeepCpaBid" slot-scope="text">{{ text / 1000 }}</span>
+        
         <span slot="action" slot-scope="text, record">
           <a @click="handleEdit(record)">编辑</a>
 
@@ -104,6 +106,12 @@ export default {
           scopedSlots: { customRender: 'maxBid' }
         },
         {
+          title: '最高转化出价',
+          align: 'center',
+          dataIndex: 'maxDeepCpaBid',
+          scopedSlots: { customRender: 'maxDeepCpaBid' }
+        },
+        {
           title: '运营负责人',
           align: 'center',
           dataIndex: 'responsibleName'

+ 38 - 1
src/views/modules/advertiser/modules/ProjectModal.vue

@@ -33,9 +33,41 @@
             }}</a-select-option>
           </a-select>
         </a-form-item>
+        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="客户类型">
+          <a-select
+            v-decorator="['advertiserType', validatorRules.advertiserId]"
+          >
+            <a-select-option :value="1">自拓客户</a-select-option>
+            <a-select-option :value="2">公司客户</a-select-option>
+            <a-select-option :value="3">代理商</a-select-option>
+          </a-select>
+          <!-- 1:自拓客户 2:公司客户  3:代理商 -->
+        </a-form-item>
+        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="销售" v-if="getFormFieldValue('advertiserType')==1||getFormFieldValue('advertiserType')==2">
+          <a-select
+            showSearch
+            optionFilterProp="children"
+            style="width: 100%"
+            @focus="handleFocus"
+            @blur="handleBlur"
+            @change="handleChange"
+            :filterOption="filterOption"
+            v-decorator="['saleId', { rules: [{ required: true, message: '请选择销售' }] }]"
+          >
+            <a-select-option
+              v-for="appModel in options"
+              :key="appModel.userId + new Date().getTime()"
+              :value="appModel.userId"
+              >{{ appModel.realName }}&#12288;&#12288;{{ appModel.roleName }}</a-select-option
+            >
+          </a-select>
+        </a-form-item>
         <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="最高出价">
           <a-input placeholder="请输入最高出价" v-decorator="['maxBid', validatorRules.maxBid]" addonAfter="元" />
         </a-form-item>
+        <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="最高转化出价">
+          <a-input placeholder="最高转化出价" v-decorator="['maxDeepCpaBid', validatorRules.maxBid]" addonAfter="元" />
+        </a-form-item>
         <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="运营负责人">
           <a-select
             showSearch
@@ -182,6 +214,7 @@ export default {
       this.form.resetFields()
       this.model = Object.assign({}, params)
       this.model.maxBid = this.model.maxBid ? this.model.maxBid / 1000 : 0
+      this.model.maxDeepCpaBid = this.model.maxDeepCpaBid ? this.model.maxDeepCpaBid / 1000 : 0
       this.visible = true
       this.$nextTick(() => {
         this.form.setFieldsValue(
@@ -191,9 +224,12 @@ export default {
             'advertiserId',
             'responsibleName',
             'maxBid',
+            'maxDeepCpaBid',
             'userId',
             'designResponsibleId',
-            'responsibleId'
+            'responsibleId',
+            'advertiserType',
+            'saleId'
           )
         )
         // this.resId = record.responsibleId
@@ -229,6 +265,7 @@ export default {
           var data = values.advertiserId
           let formData = Object.assign(this.model, values)
           formData.maxBid = formData.maxBid * 1000
+          formData.maxDeepCpaBid = formData.maxDeepCpaBid*1000
           //时间格式化
           formData.advertiserId = data.key
           formData.advertiserName = data.label

BIN
src/views/modules/material/douyin.jpg


BIN
src/views/modules/material/douyinhui.jpg


File diff suppressed because it is too large
+ 1131 - 0
src/views/modules/material/excellentMaterial.vue


BIN
src/views/modules/material/kuaishou.jpg


File diff suppressed because it is too large
+ 962 - 984
src/views/modules/material/materialList.vue


File diff suppressed because it is too large
+ 989 - 1005
src/views/modules/material/videoMaterial.vue


+ 27 - 1
src/views/ureport/UReportFileList.vue

@@ -18,7 +18,13 @@
         </a-row>
       </a-form>
     </div>
-
+    <a-row :gutter="24" style="margin-bottom:10px">
+        <a-col :md="6" :sm="8">
+        <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
+            <a-button type="primary" @click="addData">新增</a-button>
+        </span>
+        </a-col>
+    </a-row>
     <!-- table区域-begin -->
     <div>
       <a-table
@@ -37,6 +43,8 @@
 
           <a-divider type="vertical" />
           <a @click="deleteParams(record)">解绑</a>
+          <a-divider type="vertical" />
+          <a @click="editData(record)">修改</a>
         </span>
       </a-table>
     </div>
@@ -178,6 +186,24 @@ export default {
       this.fileId = item.id
       this.getMemberList(item.id)
     },
+    editData(item) {
+      var url = ''
+      if (process.env.NODE_ENV === 'development') {
+        url = 'http://39.97.120.42:8080/jeecg-boot/ureport/designer?_u=mysql:' + item.name
+      } else if (process.env.NODE_ENV === 'production') {
+        url = 'http://39.97.120.42:8080/jeecg-boot/ureport/designer?_u=mysql:' + item.name
+      }
+      window.open(url, '_blank')
+    },
+    addData(){
+      var url = ''
+      if (process.env.NODE_ENV === 'development') {
+        url = 'http://39.97.120.42:8080/jeecg-boot/ureport/designer'
+      } else if (process.env.NODE_ENV === 'production') {
+        url = 'http://39.97.120.42:8080/jeecg-boot/ureport/designer'
+      }
+      window.open(url, '_blank')
+    },
     getMemberList(id) {
       this.memberList = []
       httpAction('/ctop/uReportFileBindUser/userList', { fileId: id }, 'post').then(res => {