zhuxinbo преди 5 години
родител
ревизия
a39161c621

+ 18 - 0
src/api/actor.js

@@ -99,6 +99,15 @@ export function fileCheck(parameter) {
     })
 }
 
+
+export function fileCheckImage(parameter) {
+    return axios({
+        url: "/file/imageCheck",
+        method: 'get',
+        params: parameter
+    })
+}
+
 export function fileInsert(parameter) {
     return axios({
         url: "/file/insert",
@@ -107,6 +116,15 @@ export function fileInsert(parameter) {
     })
 }
 
+export function fileInsertV2(parameter) {
+    return axios({
+        url: "/insertV2",
+        method: 'post',
+        data: parameter
+    })
+}
+
+
 export function fileEdit(parameter) {
     return axios({
         url: "/ctop/materialInfo/edit",

+ 7 - 4
src/mixins/JeecgListMixin.js

@@ -4,6 +4,7 @@
  * data中url定义 list为查询列表  delete为删除单条记录  deleteBatch为批量删除
  */
 import {filterObj} from '@/utils/util';
+import moment from 'moment'
 import {deleteAction, getAction, downFile} from '@/api/manage'
 import Vue from 'vue'
 import {ACCESS_TOKEN} from "@/store/mutation-types"
@@ -140,7 +141,7 @@ export const JeecgListMixin = {
       MM = MM < 10 ? '0' + MM : MM
       let d = date.getDate()
       d = d < 10 ? '0' + d : d
-      return y + '-' + MM + '-' + d + " " + '00:00:00'
+      return y + '-' + MM + '-' + d
     },
     getQueryParams() {
       //获取查询条件
@@ -149,13 +150,15 @@ export const JeecgListMixin = {
         sqp['superQueryParams'] = encodeURI(this.superQueryParams)
       }
       if(this.queryParam.createTime){
-        this.queryParam.createTime = this.editDate(this.queryParam.createTime)
+        console.log(moment(this.queryParam.createTime).format('YYYY-MM-DD'))
+        this.queryParam.createTime = moment(this.queryParam.createTime).format('YYYY-MM-DD')
       }
-      var param = Object.assign(sqp, this.queryParam, this.isorter, this.filters);
+    //   var param = Object.assign(sqp, this.queryParam, this.isorter, this.filters);
+      var param = {...this.queryParam,...this.isorter, ...this.filters}
     //   param.field = this.getQueryField();
       param.pageNo = this.ipagination.current;
       param.pageSize = this.ipagination.pageSize;
-      return filterObj(param);
+      return param
     },
     getQueryField() {
       //TODO 字段权限控制

+ 531 - 0
src/views/modules/Statistics/yicheStatistics/dayStatistics.vue

@@ -0,0 +1,531 @@
+<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;
+} */
+.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;
+}
+th div {
+  white-space: nowrap;
+}
+</style>
+<template>
+  <div class="data-statistics">
+    <a-row class="image-list-heading vm-panel">
+      <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" style="width:400px" />
+          <span style="margin-left:10px">返点比例:</span>
+          <a-input-number
+            :min="1"
+            :max="10"
+            :step="0.1"
+            v-model="discount"
+            placeholder="请输入折扣"
+            style="width:100px"
+          />
+          <span style="margin-left:10px">日期选择:</span>
+          <a-date-picker @change="getDate" :disabledDate="disabledDate" />
+          <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
+          >
+        </div>
+      </a-row>
+    </a-row>
+    <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')"
+        >
+          <div style="display:flex;margin-bottom:15px">
+            <!-- <a-select style="width: 120px" v-model="statHour" @change="getElseData" allowClear>
+              <a-select-option v-for="item of 24" :key="item - 1" :value="item - 1">{{ item - 1 }}</a-select-option>
+            </a-select> -->
+            <a-button type="primary" @click="exportExcel">导出</a-button>
+          </div>
+          <a-table
+            size="middle"
+            :columns="columns"
+            :dataSource="data"
+            bordered
+            id="outTable"
+            :pagination="ipagination"
+            :scroll="{ x: 1900 }"
+            :loading="loading"
+          >
+            <span slot="statDate" slot-scope="statDate">{{ statDate | formatDate }}</span>
+            <span slot="disCountCost" slot-scope="disCountCost">{{ disCountCost | toFixtwo }}</span>
+
+            <span slot="clickConversionRate" slot-scope="clickConversionRate">{{ clickConversionRate | getBo }}</span>
+
+            <span slot="cost" slot-scope="cost">{{ cost | toFixtwo }}</span>
+            <span slot="photoClickCost" slot-scope="photoClickCost">{{ photoClickCost | toFixtwo }}</span>
+            <span slot="impression1kCost" slot-scope="impression1kCost">{{ impression1kCost | toFixtwo }}</span>
+            <span slot="conversionPrice" slot-scope="conversionPrice">{{ conversionPrice | toFixtwo }}</span>
+            <span slot="discountConversionPrice" slot-scope="discountConversionPrice">{{
+              discountConversionPrice | toFixtwo
+            }}</span>
+            <span slot="contractRebateRealCharged" slot-scope="contractRebateRealCharged">{{
+              contractRebateRealCharged | toFixtwo
+            }}</span>
+            <span slot="actualCost" slot-scope="actualCost">{{ actualCost | toFixtwo }}</span>
+
+            <span slot="photoClickRatio" slot-scope="photoClickRatio">{{ photoClickRatio | getBo }}</span>
+            <span slot="actionRatio" slot-scope="actionRatio">{{ actionRatio | getBo }}</span>
+            <span slot="conversionRate" slot-scope="conversionRate">{{ conversionRate | getBo }}</span>
+            <span slot="photoClickRatio" slot-scope="photoClickRatio">{{ photoClickRatio | getBo }}</span>
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+  </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 { getDailyReport } from '@api/statistics'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import axios from 'axios'
+import lifting from '../components/lifting'
+import timeCheck from '../components/timeCheck'
+import Treeselect from '../components/Treeselect.vue'
+
+import { JeecgListMixin } from '@/mixins/ipagination'
+
+var length = 0
+var active = 1
+const columns = [
+  {
+    title: '消耗(¥)',
+    dataIndex: 'cost',
+    scopedSlots: { customRender: 'cost' },
+    align: 'center'
+  },
+  {
+    title: '展示数',
+    dataIndex: 'photoShow',
+    align: 'center'
+  },
+  {
+    title: '点击数',
+    dataIndex: 'photoClick',
+    align: 'center'
+  },
+  {
+    title: '点击率',
+    dataIndex: 'photoClickRatio',
+    align: 'center',
+    scopedSlots: { customRender: 'photoClickRatio' }
+  },
+  {
+    title: '平均点击花费',
+    dataIndex: 'photoClickCost',
+    align: 'center',
+    scopedSlots: { customRender: 'photoClickCost' }
+  },
+  {
+    title: '行为数',
+    dataIndex: 'bclick',
+    align: 'center'
+  },
+  {
+    title: '行为率',
+    dataIndex: 'actionRatio',
+    align: 'center',
+    scopedSlots: { customRender: 'actionRatio' }
+  },
+  {
+    title: '平均千次展示花费(¥)',
+    dataIndex: 'impression1kCost',
+    align: 'center',
+    scopedSlots: { customRender: 'impression1kCost' }
+  },
+
+  {
+    title: '转化数',
+    dataIndex: 'conversions',
+    align: 'center'
+  },
+  {
+    title: '转化单价(¥)',
+    dataIndex: 'conversionPrice',
+    align: 'center',
+    scopedSlots: { customRender: 'conversionPrice' }
+  },
+  {
+    title: '转化率',
+    dataIndex: 'conversionRate',
+    align: 'center',
+    scopedSlots: { customRender: 'conversionRate' }
+  },
+  {
+    title: '折后转化成本(¥)',
+    dataIndex: 'discountConversionPrice',
+    align: 'center',
+    scopedSlots: { customRender: 'discountConversionPrice' }
+  },
+  {
+    title: '激励花费(¥)',
+    dataIndex: 'contractRebateRealCharged',
+    align: 'center',
+    scopedSlots: { customRender: 'contractRebateRealCharged' }
+  },
+  {
+    title: '实际消耗(¥)',
+    dataIndex: 'actualCost',
+    align: 'center',
+    scopedSlots: { customRender: 'actualCost' }
+  }
+]
+
+const columnsGroup = [
+  {
+    title: '日期',
+    dataIndex: 'statDate',
+    scopedSlots: { customRender: 'statDate' },
+    align: 'center'
+  },
+  {
+    title: '账号',
+    dataIndex: 'accountId',
+    align: 'center'
+  },
+  {
+    title: '账号名称',
+    dataIndex: 'authName',
+    align: 'center'
+  },
+  {
+    title: '计划名称',
+    dataIndex: 'campaignName',
+    align: 'center'
+  },
+  {
+    title: '广告组名称',
+    dataIndex: 'unitName',
+    align: 'center'
+  },
+  {
+    title: '消耗',
+    dataIndex: 'cost',
+    align: 'center',
+    scopedSlots: { customRender: 'cost' }
+  },
+  {
+    title: '折后消耗',
+    dataIndex: 'disCountCost',
+    align: 'center',
+    scopedSlots: { customRender: 'cost' }
+  },
+  {
+    title: '展示数',
+    dataIndex: 'photoShow',
+    align: 'center'
+  },
+  {
+    title: '点击数',
+    dataIndex: 'photoClick',
+    align: 'center'
+  },
+  {
+    title: '点击率',
+    dataIndex: 'photoClickRatio',
+    align: 'center',
+    scopedSlots: { customRender: 'photoClickRatio' }
+  },
+
+  {
+    title: '行为数',
+    dataIndex: 'bclick',
+    align: 'center'
+  },
+  {
+    title: '行为率',
+    dataIndex: 'actionRatio',
+    align: 'center',
+    scopedSlots: { customRender: 'actionRatio' }
+  },
+  {
+    title: '平均千次展示花费(¥)',
+    dataIndex: 'impression1kCost',
+    align: 'center',
+    scopedSlots: { customRender: 'impression1kCost' }
+  },
+  {
+    title: '平均点击花费',
+    dataIndex: 'photoClickCost',
+    align: 'center',
+    scopedSlots: { customRender: 'photoClickCost' }
+  },
+  {
+    title: '转化数',
+    dataIndex: 'conversions',
+    align: 'center'
+  },
+  {
+    title: '转化单价(¥)',
+    dataIndex: 'conversionPrice',
+    align: 'center',
+    scopedSlots: { customRender: 'conversionPrice' }
+  },
+  {
+    title: '转化率',
+    dataIndex: 'conversionRate',
+    align: 'center',
+    scopedSlots: { customRender: 'conversionRate' }
+  },
+  {
+    title: '折后转化成本(¥)',
+    dataIndex: 'discountConversionPrice',
+    align: 'center',
+    scopedSlots: { customRender: 'discountConversionPrice' }
+  },
+  {
+    title: '点击转化率',
+    dataIndex: 'clickConversionRate',
+    align: 'center',
+    scopedSlots: { customRender: 'clickConversionRate' }
+  }
+]
+
+export default {
+  name: 'data-display-statistics',
+  components: {
+    ACol,
+    ARow,
+    countTo,
+    lifting,
+    timeCheck,
+    Treeselect
+  },
+  mixins: [JeecgListMixin],
+  data: function() {
+    return {
+      title: '账户数据展示',
+      show: true,
+      data: [],
+      dataAll: null,
+      columns: columns,
+      options: [],
+      list: [],
+      appId: [],
+      tabListNoTitle: [
+        {
+          key: 'day',
+          tab: '分日数据'
+        },
+        {
+          key: 'group',
+          tab: '分组数据'
+        }
+      ],
+      noTitleKey: 'day',
+      discount: 1,
+      date: '',
+      loading: false
+    }
+  },
+  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
+    },
+    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,
+    
+    onTabChange(key, type) {
+      console.log(key, type)
+      this[type] = key
+      this.data = []
+      if (key == 'day') {
+        this.columns = columns
+        this.data.push({ ...this.dataAll.dailyAccountReport, key: 1 })
+      } else {
+        this.columns = columnsGroup
+        this.data = this.dataAll.dailyGroupReport.map((item, index) => {
+          return {
+            ...item,
+            key: index
+          }
+        })
+      }
+      this.ipagination.total = this.data.length
+      this.ipagination.current = 1
+    },
+    disabledDate(current) {
+      return current && current > moment().subtract(1, 'day')
+    },
+    getDataReset() {
+      this.addUser()
+    },
+    addUser() {
+      var that = this
+      if (this.appId.length > 0 && this.date != '') {
+        that.getDailyReport()
+      } else {
+        this.$message.error('请选择账户及时间')
+      }
+    },
+    getDailyReport() {
+      var params = {}
+      params.accountIds = JSON.stringify(this.appId)
+      params.date = this.date
+      params.discount = this.discount
+      this.data = []
+      this.loading = true
+      getDailyReport(params).then(res => {
+        if (res.success) {
+          this.loading = false
+          this.dataAll = res.result
+          if (this.noTitleKey == 'day') {
+            this.data.push({ ...res.result.dailyAccountReport, key: 1 })
+          } else {
+            this.data = res.result.dailyGroupReport.map((item, index) => {
+              return {
+                ...item,
+                key: index
+              }
+            })
+          }
+          this.ipagination.total = this.data.length
+        }
+      })
+    },
+    getDate(value) {
+      if (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
+        this.date = y + '-' + MM + '-' + d
+      } else {
+        let date = new Date()
+        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
+        this.date = y + '-' + MM + '-' + d
+      }
+    },
+    exportExcel() {
+      var params = {}
+      params.accountIds = JSON.stringify(this.appId)
+      params.date = this.date
+      params.discount = this.discount
+      downFilePost('/ctop/daily/exportDailyReport', params).then(res => {
+        let blob = new Blob([res], {
+          type: 'application/vnd.ms-excel'
+        })
+        let downloadElement = document.createElement('a')
+        let href = window.URL.createObjectURL(blob) //创建下载的链接
+        downloadElement.href = href
+        downloadElement.download = this.date + '-日报' //下载后文件名
+        document.body.appendChild(downloadElement)
+        downloadElement.click() //点击下载
+        document.body.removeChild(downloadElement) //下载完成移除元素
+        window.URL.revokeObjectURL(href) //释放掉blob对象
+      })
+    }
+  },
+  watch: {},
+  distoryed() {},
+  mounted: function() {
+    this.$nextTick(() => {})
+  }
+}
+</script>

+ 391 - 0
src/views/modules/Statistics/yicheStatistics/timeStatistics.vue

@@ -0,0 +1,391 @@
+<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;
+} */
+.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;
+}
+th div {
+  white-space: nowrap;
+}
+</style>
+<template>
+  <div class="data-statistics">
+    <a-row class="image-list-heading vm-panel">
+      <a-row type="flex" align="middle" justify="space-between" class="panel-body">
+        <div class="search-bar" style="width:100%">
+          <span>账户选择:</span>
+          <a-select
+            v-model="projectId"
+            style="width:500px"
+            showSearch
+            optionFilterProp="children"
+            :filterOption="filterOption"
+          >
+            <a-select-option :value="item.projectId" v-for="item of dataElse" :key="item.id">
+              {{ item.projectName }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{
+                item.mediaId == '1' ? '头条' : '快手'
+              }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ item.advertiserName }}
+            </a-select-option>
+          </a-select>
+          <span style="margin-left:10px">返点比例:</span>
+          <a-input-number
+            :min="1"
+            :max="10"
+            :step="0.01"
+            v-model="discount"
+            placeholder="请输入折扣"
+            style="width:100px"
+          />
+          <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
+          >
+        </div>
+      </a-row>
+    </a-row>
+    <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')"
+        >
+          <div style="display:flex;margin-bottom:15px">
+            <!-- <a-select style="width: 120px" v-model="statHour" @change="getElseData" allowClear>
+              <a-select-option v-for="item of 24" :key="item - 1" :value="item - 1">{{ item - 1 }}</a-select-option>
+            </a-select> -->
+            <a-button type="primary" @click="exportExcel">导出</a-button>
+          </div>
+          <a-table
+            size="middle"
+            :columns="columns"
+            :dataSource="data"
+            bordered
+            id="outTable"
+            :pagination="ipagination"
+            :scroll="{ x: true }"
+            :loading="loading"
+          >
+          </a-table>
+        </a-card>
+      </a-col>
+    </a-row>
+  </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 { getDailyReport } from '@api/statistics'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import axios from 'axios'
+import lifting from '../components/lifting'
+import timeCheck from '../components/timeCheck'
+import Treeselect from '../components/Treeselect.vue'
+import { mapGetters } from 'vuex'
+import { JeecgListMixin } from '@/mixins/ipagination'
+
+var length = 0
+var active = 1
+const columns = [
+  {
+    title: '投放设备',
+    dataIndex: 'systemType',
+    scopedSlots: { customRender: 'systemType' },
+    align: 'center'
+  },
+  {
+    title: '分类',
+    dataIndex: 'authName',
+    scopedSlots: { customRender: 'authName' },
+    align: 'center'
+  },
+  {
+    title: '现金花费',
+    dataIndex: 'charge',
+    align: 'center'
+  },
+  {
+    title: '账户激活量',
+    dataIndex: 'activation',
+    align: 'center'
+  },
+  {
+    title: '激活成本',
+    dataIndex: 'activationCost',
+    align: 'center',
+    scopedSlots: { customRender: 'activationCost' }
+  },
+  {
+    title: '预估成本',
+    dataIndex: 'estimatedCost',
+    align: 'center',
+    scopedSlots: { customRender: 'estimatedCost' }
+  }
+]
+
+const columnsGroup = columns
+
+export default {
+  name: 'data-display-statistics',
+  components: {
+    ACol,
+    ARow,
+    countTo,
+    lifting,
+    timeCheck,
+    Treeselect
+  },
+  mixins: [JeecgListMixin],
+  data: function() {
+    return {
+      title: '账户数据展示',
+      show: true,
+      data: [],
+      dataAll: null,
+      columns: columns,
+      options: [],
+      list: [],
+      appId: [],
+      tabListNoTitle: [
+        {
+          key: 'day',
+          tab: '安卓'
+        },
+        {
+          key: 'group',
+          tab: 'ios'
+        }
+      ],
+      noTitleKey: 'day',
+      discount: 1.06,
+      date: '',
+      loading: false,
+      dataElse: [],
+      projectId: 50
+    }
+  },
+  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
+    },
+    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,
+    filterOption(input, option) {
+      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+    },
+    ...mapGetters(['nickname', 'avatar', 'userInfo']),
+    getParticipateList() {
+      getAction('/ctop/projectMember/participateList', {
+        userId: this.userInfo().id
+      }).then(res => {
+        if (res.code == 0) {
+          this.dataElse = res.result
+        }
+      })
+    },
+    onTabChange(key, type) {
+      console.log(key, type)
+      this[type] = key
+      this.data = []
+      if (key == 'day') {
+        this.columns = columns
+        this.data = this.dataAll.android.map((item, index) => {
+          return {
+            ...item,
+            key: index
+          }
+        })
+      } else {
+        this.columns = columnsGroup
+        this.data = this.dataAll.ios.map((item, index) => {
+          return {
+            ...item,
+            key: index
+          }
+        })
+      }
+      this.ipagination.total = this.data.length
+      this.ipagination.current = 1
+    },
+    disabledDate(current) {
+      return current && current > moment().subtract(1, 'day')
+    },
+    getDataReset() {
+      this.addUser()
+    },
+    addUser() {
+      var that = this
+      //   if (this.appId.length > 0 && this.date != '') {
+      that.getDailyReport()
+      //   } else {
+      //     this.$message.error('请选择账户及时间')
+      //   }
+    },
+    getDailyReport() {
+      var params = {}
+      params.projectId = this.projectId
+      params.disCount = this.discount
+      this.data = []
+      this.loading = true
+      postAction('/ctop/yiche/report/hourReport', params).then(res => {
+        if (res.success) {
+          this.loading = false
+          this.dataAll = res.result
+          console.log(res)
+          if (this.noTitleKey == 'day') {
+            this.data = res.result.android.map((item, index) => {
+              return {
+                ...item,
+                key: index
+              }
+            })
+          } else {
+            this.data = res.result.ios.map((item, index) => {
+              return {
+                ...item,
+                key: index
+              }
+            })
+          }
+          this.ipagination.total = this.data.length
+        }
+      })
+    },
+    getDate(value) {
+      if (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
+        this.date = y + '-' + MM + '-' + d
+      } else {
+        let date = new Date()
+        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
+        this.date = y + '-' + MM + '-' + d
+      }
+    },
+    exportExcel() {
+      var params = {}
+      params.projectId = this.projectId
+      params.disCount = this.discount
+      var name = this.dataElse.filter(item => {
+        return item.projectId == this.projectId
+      })[0].projectName
+      downFilePost('/ctop/yiche/report/exportHourReport', params).then(res => {
+        let blob = new Blob([res], {
+          type: 'application/vnd.ms-excel'
+        })
+        let downloadElement = document.createElement('a')
+        let href = window.URL.createObjectURL(blob) //创建下载的链接
+        downloadElement.href = href
+        downloadElement.download = name + '-时报' //下载后文件名
+        document.body.appendChild(downloadElement)
+        downloadElement.click() //点击下载
+        document.body.removeChild(downloadElement) //下载完成移除元素
+        window.URL.revokeObjectURL(href) //释放掉blob对象
+      })
+    }
+  },
+  watch: {},
+  distoryed() {},
+  mounted: function() {
+    this.getParticipateList()
+  }
+}
+</script>

+ 7 - 5
src/views/modules/material/materialList.vue

@@ -200,7 +200,8 @@ a {
           </a-col> -->
           <a-col :md="8" :sm="8">
             <a-form-item label="时间选择">
-              <a-date-picker v-model="queryParam.createTime" format="YYYY-MM-DD" style="width:100%" />
+              <!-- <a-date-picker v-model="queryParam.createTime" format="YYYY-MM-DD" style="width:100%" /> -->
+              <a-input placeholder="请输入查询时间" v-model="queryParam.createTime"></a-input>
             </a-form-item>
           </a-col>
           <a-col :md="8" :sm="8">
@@ -1007,11 +1008,12 @@ export default {
       this.checkAll = !this.checkAll
     },
     searchRe() {
-      this.queryParam.projectId = ''
-      if (this.queryParam.createTime) {
-        this.queryParam.createTime = ''
+      this.queryParam = {
+        type: 'IMAGE',
+        userId: this.userInfo().id,
+        status: this.active
       }
-      this.loadData()
+      this.loadData(1)
     },
     getList(value) {
       if (value) {

+ 159 - 62
src/views/modules/material/videoMaterial.vue

@@ -68,6 +68,9 @@
 .cover_carousel_con .slick-dots {
   bottom: 55px;
 }
+.add-image-material .draggable-list {
+  display: block !important;
+}
 </style>
 <style lang="scss" scoped>
 .tag-video {
@@ -269,7 +272,8 @@ a {
           </a-col>
           <a-col :md="8" :sm="8">
             <a-form-item label="时间选择">
-              <a-date-picker v-model="queryParam.createTime" format="YYYY-MM-DD" style="width:100%" />
+              <!-- <a-date-picker v-model="queryParam.createTime" format="YYYY-MM-DD" style="width:100%" /> -->
+              <a-input placeholder="请输入查询时间" v-model="queryParam.createTime"></a-input>
             </a-form-item>
           </a-col>
           <a-col :md="8" :sm="8">
@@ -566,14 +570,14 @@ a {
         </div>
       </a-tab-pane>
     </a-tabs>
-    <a-modal title="封面上传" v-model="addImageVisible">
+    <a-modal title="封面上传" @cancel="closeImage" @afterClose="closeImage" v-model="addImageVisible">
       <template slot="footer">
         <a-button key="back" @click="closeImage">取消</a-button>
         <a-button key="submit" type="primary" @click="handleOkImage">
           确定
         </a-button>
       </template>
-      <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="" class="add-image-material">
+      <a-form-item label="" class="add-image-material">
         <upload-to-ali
           style="width:100%"
           v-model="urlListImage.url"
@@ -630,7 +634,7 @@ a {
       </div>
     </a-modal>
 
-    <a-modal title="添加素材" v-model="visible" :maskClosable="false" :width="800">
+    <a-modal title="添加素材" v-model="visible" @cancel="close" @afterClose="close" :maskClosable="false" :width="800">
       <template slot="footer">
         <a-button key="back" @click="close">取消</a-button>
         <a-button key="submit" type="primary" :disabled="!confirmLoading" @click="handleOk">
@@ -822,18 +826,30 @@ a {
             您的浏览器不支持 video 标签。
           </video>
           <div class="downLoad" style="height:50%;overflow:auto">
+            <a-button @click="onCheckAllImageChange" v-if="model.length > 0">{{
+              checkAllImage ? '取消  (  ' + checkArrImage.length + '  )' : '全选'
+            }}</a-button>
             <ul class="actor-photo-list" :style="{ width: 25 * model.length + '%' }" v-if="model.length > 0">
               <a-checkbox-group
                 v-model="checkArrImage"
                 style="width:100%;  display: flex;padding-left: 0;"
-                @change="onChangeCheck"
+                @change="onChangeCheckImage"
               >
                 <li v-for="(item, index) of model" :key="index">
-                  <a-checkbox :value="item" style="position:absolute;z-index: 100"></a-checkbox
+                  <a-checkbox :value="item.id" style="position:absolute;z-index: 100"></a-checkbox
                   ><img class="video" :src="item.url" @click="coverPreviewShowModal(item, index)" />
-                  <span class="tag-video">{{
-                    item.status == 0 ? '未审核' : item.status == 1 ? '已批准' : '已驳回'
-                  }}</span>
+                  <span
+                    class="tag-video"
+                    :style="{
+                      backgroundColor:
+                        item.status == 0
+                          ? 'rgba(0, 0, 0)'
+                          : item.status == 1
+                          ? 'rgba(0, 180, 100)'
+                          : 'red'
+                    }"
+                    >{{ item.status == 0 ? '未审核' : item.status == 1 ? '已批准' : '已驳回' }}</span
+                  >
                 </li>
               </a-checkbox-group>
             </ul>
@@ -844,14 +860,27 @@ a {
         </div>
         <a-modal title="图片预览" v-model="coverPreviewVisible" :footer="null">
           <a-carousel arrows class="cover_carousel_con">
-            <div v-for="(item, index) in model" :key="index" class="content">
+            <div v-for="(item, index) in modelNew" :key="index" class="content">
               <img :src="item.url" :width="300" />
               <div style="margin-top:10px">
-                <a-button type="primary">
+                <a-button type="primary" @click="editImage(item, '1')">
                   通过审核
                 </a-button>
                 <a-divider type="vertical" />
-                <a-button type="primary">驳回</a-button>
+                <a-popconfirm @confirm="editImage(item, '2')">
+                  <div slot="title">
+                    <div>
+                      驳回原因:
+                      <a-textarea
+                        placeholder="请输入原因"
+                        v-model="refuseReasonImage"
+                        :autosize="{ minRows: 3, maxRows: 10 }"
+                      />
+                    </div>
+                  </div>
+                  <a-button type="primary">驳回</a-button>
+                  <!-- @click="edit(null, '0', '2')" -->
+                </a-popconfirm>
               </div>
             </div>
             <a-icon
@@ -961,7 +990,7 @@ a {
             </div>
             <div>
               <a-form-item
-                label="审核"
+                label="视频审核"
                 v-if="
                   active != '2' &&
                     (role.roleCode == 'operator' ||
@@ -1023,55 +1052,29 @@ a {
                 </a-popconfirm>
               </a-form-item>
             </div>
-            <!-- <div class="downLoad">
-              <a-form-item label="封面" style="width:120%">
-                <a-table
-                  bordered
-                  size="middle"
-                  :columns="goodsColumns"
-                  :dataSource="model"
-                  :pagination="{ pageSize: 4 }"
-                  :scroll="{ y: 200 }"
+            <div>
+              <a-form-item label="封面审核" style="width:120%">
+                <a-button type="primary" :disabled="checkArrImage.length == 0" @click="editImageAll('1')"
+                  >通过审核</a-button
                 >
-                  <div slot="url" slot-scope="text, record, index">
+                <a-popconfirm @confirm="editImageAll('2')" v-show="active != '2'">
+                  <div slot="title">
                     <div>
-                      <img style="max-width:100px" :src="text" @click="coverPreviewShowModal(record, index)" />
+                      驳回原因:
+                      <a-textarea
+                        placeholder="请输入原因"
+                        v-model="refuseReasonImage"
+                        :autosize="{ minRows: 3, maxRows: 10 }"
+                      />
                     </div>
-                    <a-modal title="图片预览" v-model="coverPreviewVisible" :footer="null">
-                      <a-carousel arrows class="cover_carousel_con">
-                        <div v-for="(item, index) in model" :key="index" class="content">
-                          <img :src="item.url" :width="300" />
-                          <div style="margin-top:10px">
-                            <a-button type="primary" @click="handleOk">
-                              通过审核
-                            </a-button>
-                            <a-divider type="vertical" />
-                            <a-button type="primary" @click="close">驳回</a-button>
-                          </div>
-                        </div>
-                        <a-icon
-                          type="left-circle"
-                          slot="prevArrow"
-                          slot-scope
-                          style="left: 10px;zIndex: 9;font-size:30px;color:black"
-                        />
-                        <a-icon
-                          type="right-circle"
-                          slot="nextArrow"
-                          slot-scope
-                          style="right: 10px;zIndex: 9;font-size:30px;color:black"
-                        />
-                      </a-carousel>
-                    </a-modal>
-                  </div>
-                  <div slot="action" slot-scope="text, record">
-                    <a>通过{{ record.key }}</a>
-                    <a-divider type="vertical" />
-                    <a>驳回</a>
                   </div>
-                </a-table>
+                  <a-button type="primary" :disabled="checkArrImage.length != 1" style="margin-left:10px"
+                    >驳回</a-button
+                  >
+                  <!-- @click="edit(null, '0', '2')" -->
+                </a-popconfirm>
               </a-form-item>
-            </div> -->
+            </div>
           </a-form>
         </div>
       </div>
@@ -1086,7 +1089,7 @@ import { JeecgListMixin } from '@/mixins/JeecgListMixin'
 import JEllipsis from '@/components/jeecg/JEllipsis'
 import UploadToAli from '@femessage/upload-to-ali'
 import { fileCheck, fileInsertV2, fileEdit, fileCheckImage } from '@/api/actor'
-import { getAction, postAction, postFile, deleteAction } from '@/api/manage'
+import { getAction, postAction, postFile, deleteAction, putAction } from '@/api/manage'
 import qs from 'qs'
 import { mapGetters } from 'vuex'
 import moment from 'moment'
@@ -1110,6 +1113,7 @@ export default {
     return {
       coverPreviewVisible: false,
       model: [],
+      modelNew: [],
       goodsColumns: [
         {
           title: '封面预览',
@@ -1203,6 +1207,7 @@ export default {
       tags: [],
       refuseFile: [],
       refuseReason: '',
+      refuseReasonImage: '',
       creativeCopywriter: '',
       customDomain: '',
       region: 'oss-cn-beijing',
@@ -1214,6 +1219,7 @@ export default {
       checkArr: [],
       checkAll: false,
       checkArrImage: [],
+      checkAllImage: false,
       showUrl: '',
       showUrlWater: '',
       materialName: '',
@@ -1312,6 +1318,75 @@ export default {
     }
   },
   methods: {
+    editImage(item, status) {
+      var params = {}
+      params.id = item.id
+      params.status = status
+      if (status == '1') {
+      } else {
+        params.refuseReason = this.refuseReasonImage
+      }
+      var updateArr = [params]
+      putAction('/ctop/MaterialImageInfo/batchEdit', updateArr).then(res => {
+        console.log(res)
+        if (res.success) {
+          //   this.coverPreviewVisible = false
+          getAction('/ctop/MaterialImageInfo/list', {
+            videoId: this.code
+          }).then(res => {
+            if (res.success) {
+              this.model = res.result.map((item, index) => {
+                return {
+                  ...item,
+                  key: index
+                }
+              })
+              this.modelNew = this.model.filter((item, index) => {
+                return item.status == '0'
+              })
+              if (this.modelNew.length == 0) {
+                this.coverPreviewVisible = false
+              }
+            }
+          })
+        }
+      })
+    },
+    editImageAll(status) {
+      this.checkArrImage
+      //   var params = {}
+      //   params.id = item.id
+      //   params.status = status
+      var updateArr = []
+      if (status == '1') {
+        updateArr = this.checkArrImage.map(item => {
+          return { id: item, status: status }
+        })
+      } else {
+        updateArr = this.checkArrImage.map(item => {
+          return { id: item, status: status, refuseReason: this.refuseReasonImage }
+        })
+      }
+      putAction('/ctop/MaterialImageInfo/batchEdit', updateArr).then(res => {
+        if (res.success) {
+          //   this.coverPreviewVisible = false
+          getAction('/ctop/MaterialImageInfo/list', {
+            videoId: this.code
+          }).then(res => {
+            if (res.success) {
+              this.checkArrImage = []
+              this.checkAllImage = false
+              this.model = res.result.map((item, index) => {
+                return {
+                  ...item,
+                  key: index
+                }
+              })
+            }
+          })
+        }
+      })
+    },
     showData(item) {
       if (item.byteDance || item.kuaiShou) {
         this.showDataBool = true
@@ -1429,10 +1504,21 @@ export default {
       }
       this.checkAll = !this.checkAll
     },
+    onCheckAllImageChange() {
+      if (this.checkAllImage) {
+        this.checkArrImage = []
+      } else {
+        this.checkArrImage = this.model.map(item => {
+          return item.id
+        })
+      }
+      this.checkAllImage = !this.checkAllImage
+    },
     searchRe() {
-      this.queryParam.projectId = ''
-      if (this.queryParam.createTime) {
-        this.queryParam.createTime = ''
+      this.queryParam = {
+        type: 'VIDEO',
+        userId: this.userInfo().id,
+        status: this.active
       }
       this.loadData(1)
     },
@@ -1446,6 +1532,11 @@ export default {
       }
       this.loadData()
     },
+    onChangeCheckImage(checkedList) {
+      if (checkedList.length == 0) {
+        this.checkAllImage = false
+      }
+    },
     onChangeCheck(checkedList) {
       if (checkedList.length == 0) {
         this.checkAll = false
@@ -1547,7 +1638,13 @@ export default {
       })
     },
     coverPreviewShowModal(item, index) {
-      this.coverPreviewVisible = true
+      console.log(this.model)
+      this.modelNew = this.model.filter(items => {
+        return items.status == 0
+      })
+      if (this.modelNew.length > 0) {
+        this.coverPreviewVisible = true
+      }
     },
     okEditShow(item, editStatus) {
       if (editStatus == '2') {

+ 4 - 4
vue.config.js

@@ -65,13 +65,13 @@ module.exports = {
        },*/
       '/jeecg-boot': {
         // target: 'http://39.97.120.42:8080', //请求本地 需要jeecg-boot后台项目  生产环境
-        target: 'http://39.106.184.70:8080', //请求本地 需要jeecg-boot后台项目
-        // target: 'http://192.168.2.118:8080', //请求本地 需要jeecg-boot后台项目  蒙蒙
+        // target: 'http://39.106.184.70:8080', //请求本地 需要jeecg-boot后台项目
+        target: 'http://192.168.2.138:8080', //请求本地 需要jeecg-boot后台项目  蒙蒙
         // target: 'http://192.168.2.110:8080', //请求本地 需要jeecg-boot后台项目  英豪
         // target: 'http://192.168.2.132:8080', //请求本地 需要jeecg-boot后台项目
         // target: 'http://192.168.2.115:8080', //请求本地 需要jeecg-boot后台项目  祚云
-        // target: 'http://192.168.2.123:8080', //请求本地 需要jeecg-boot后台项目  孙震
-        // target:'http://127.0.0.1:8080',
+        // target: 'http://192.168.2.124:8080', //请求本地 需要jeecg-boot后台项目  孙震
+        // target: 'http://192.168.43.119:8080', //请求本地 需要jeecg-boot后台项目  蒙蒙,手机热点
         ws: false,
         changeOrigin: true
       },