Ver Fonte

feat: online duration report

Casper Dai há 2 anos atrás
pai
commit
15fad4ae5e

+ 30 - 0
src/views/realm/report/api.js

@@ -97,3 +97,33 @@ export function getOnlineDurationExcel () {
     download(response, `在线时长${parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')}.xlsx`)
   })
 }
+
+export function getRangeOnlineDurationExcel (data, fileName = '') {
+  return send({
+    url: '/excel/export?type=DEVICE_ONLINE_RANGEDAY',
+    method: 'POST',
+    data: addTenant(data)
+  }, downloadRequest).then(response => {
+    download(response, `在线时长${parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')}_${fileName}.xlsx`)
+  })
+}
+
+export function getDepartmentOnlineDurationExcel (department, fileName = '') {
+  return send({
+    url: '/excel/export?type=DEVICE_ONLINE_TOTAL',
+    method: 'POST',
+    data: { department }
+  }, downloadRequest).then(response => {
+    download(response, `在线时长${parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')}_${fileName}.xlsx`)
+  })
+}
+
+export function getDepartmentRangeOnlineDurationExcel (data, fileName = '') {
+  return send({
+    url: '/excel/export?type=DEVICE_ONLINE_RANGEDAY',
+    method: 'POST',
+    data
+  }, downloadRequest).then(response => {
+    download(response, `在线时长${parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')}_${fileName}.xlsx`)
+  })
+}

+ 1 - 1
src/views/realm/report/components/MaterialDialog.vue → src/views/realm/report/components/MaterialConfigDialog.vue

@@ -25,7 +25,7 @@
 import { getMaterialExcel } from '../api'
 
 export default {
-  name: 'MaterialDialog',
+  name: 'MaterialConfigDialog',
   data () {
     return {
       recursive: false

+ 91 - 0
src/views/realm/report/components/OnlineDurationDialog.vue

@@ -0,0 +1,91 @@
+<template>
+  <confirm-dialog
+    ref="dialog"
+    size="lg fixed"
+    title="在线时长报表"
+    @confirm="onConfirm"
+  >
+    <template #default>
+      <div class="l-flex__fill l-flex">
+        <department-tree
+          class="c-sibling-item c-sidebar u-width--xl"
+          @change="onGroupChanged"
+        />
+        <div class="c-sibling-item far">
+          <div class="c-sibling-item--v u-required">日期范围</div>
+          <el-date-picker
+            v-model="dateRange"
+            class="c-sibling-item--v"
+            type="daterange"
+            range-separator="至"
+            value-format="yyyy-MM-dd"
+            :picker-options="pickerOptions"
+            :editable="false"
+          />
+        </div>
+      </div>
+    </template>
+  </confirm-dialog>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+import { parseTime } from '@/utils'
+import {
+  getOnlineDurationExcel,
+  getRangeOnlineDurationExcel,
+  getDepartmentOnlineDurationExcel,
+  getDepartmentRangeOnlineDurationExcel
+} from '../api'
+
+export default {
+  name: 'OnlineDurationDialog',
+  data () {
+    return {
+      dateRange: []
+    }
+  },
+  computed: {
+    ...mapGetters(['tenant']),
+    pickerOptions () {
+      return {
+        disabledDate: this.isDisableDate
+      }
+    }
+  },
+  methods: {
+    show () {
+      this.dateRange = [parseTime(new Date() - 3600000 * 24 * 6, '{y}-{m}-{d}'), parseTime(new Date(), '{y}-{m}-{d}')]
+      this.$refs.dialog.show()
+    },
+    onGroupChanged (group) {
+      this.$group = group
+    },
+    isDisableDate (date) {
+      return date > Date.now()
+    },
+    onConfirm (done) {
+      const groupPath = this.$group.path
+      if (this.dateRange) {
+        const time = this.dateRange[0] === this.dateRange[1] ? this.dateRange[0] : `${this.dateRange[0]}~${this.dateRange[1]}`
+        if (this.tenant === groupPath) {
+          getRangeOnlineDurationExcel({
+            sumDateFrom: this.dateRange[0],
+            sumDateTo: this.dateRange[1]
+          }, time).then(done)
+        } else {
+          getDepartmentRangeOnlineDurationExcel({
+            department: this.$group.path,
+            sumDateFrom: this.dateRange[0],
+            sumDateTo: this.dateRange[1]
+          }, `${this.$group.name}_${time}`).then(done)
+        }
+      } else if (this.tenant === groupPath) {
+        getOnlineDurationExcel().then(done)
+      } else {
+        getDepartmentOnlineDurationExcel(this.$group.path, this.$group.name).then(done)
+      }
+    }
+  }
+}
+</script>

+ 41 - 29
src/views/realm/report/index.vue

@@ -5,30 +5,30 @@
     padding
     background
   >
-    <template v-if="isTopGroupAdmin">
-      <div class="c-sibling-item--v u-font-size--sm u-bold">平台数据</div>
-      <div class="c-sibling-item--v near l-grid--info mini">
-        <button
-          class="o-button"
-          @click="getDeviceExcel"
-        >
-          设备报表
-        </button>
-        <button
-          class="o-button"
-          @click="getContentExcel"
-        >
-          内容播放报表
-        </button>
-        <button
-          class="o-button"
-          @click="getOnlineDurationExcel"
-        >
-          在线时长报表
-        </button>
-      </div>
-    </template>
     <template v-if="isGroupAdmin">
+      <template v-if="isTopGroup">
+        <div class="c-sibling-item--v u-font-size--sm u-bold">平台数据</div>
+        <div class="c-sibling-item--v near l-grid--info mini">
+          <button
+            class="o-button"
+            @click="getDeviceExcel"
+          >
+            设备报表
+          </button>
+          <button
+            class="o-button"
+            @click="getContentExcel"
+          >
+            内容播放报表
+          </button>
+          <button
+            class="o-button"
+            @click="getOnlineDurationExcel"
+          >
+            总在线时长报表
+          </button>
+        </div>
+      </template>
       <div class="c-sibling-item--v u-font-size--sm u-bold">部门数据</div>
       <div class="c-sibling-item--v near l-grid--info mini">
         <button
@@ -49,6 +49,12 @@
         >
           三审报表
         </button>
+        <button
+          class="o-button"
+          @click="getDepartmentOnlineDurationExcel"
+        >
+          在线时长报表
+        </button>
       </div>
     </template>
     <div class="c-sibling-item--v u-font-size--sm u-bold">设备数据</div>
@@ -66,12 +72,13 @@
         广告播放
       </button>
     </div>
-    <material-dialog ref="materialDialog" />
+    <material-config-dialog ref="materialConfigDialog" />
     <account-dialog ref="accountDialog" />
     <audit-dialog ref="auditDialog" />
     <content-dialog ref="contentDialog" />
     <program-guide-dialog ref="programGuideDialog" />
     <device-ad-dialog ref="deviceAdDialog" />
+    <online-duration-dialog ref="onlineDurationDialog" />
   </wrapper>
 </template>
 
@@ -81,25 +88,27 @@ import {
   getDeviceExcel,
   getOnlineDurationExcel
 } from './api'
-import MaterialDialog from './components/MaterialDialog.vue'
+import MaterialConfigDialog from './components/MaterialConfigDialog.vue'
 import AccountDialog from './components/AccountDialog.vue'
 import AuditDialog from './components/AuditDialog.vue'
 import ContentDialog from './components/ContentDialog.vue'
 import ProgramGuideDialog from './components/ProgramGuideDialog.vue'
 import DeviceAdDialog from './components/DeviceAdDialog.vue'
+import OnlineDurationDialog from './components/OnlineDurationDialog.vue'
 
 export default {
   name: 'Report',
   components: {
-    MaterialDialog,
+    MaterialConfigDialog,
     AccountDialog,
     AuditDialog,
     ContentDialog,
     ProgramGuideDialog,
-    DeviceAdDialog
+    DeviceAdDialog,
+    OnlineDurationDialog
   },
   computed: {
-    ...mapGetters(['isTopGroupAdmin', 'isGroupAdmin'])
+    ...mapGetters(['isGroupAdmin', 'isTopGroup'])
   },
   watch: {
     deviceId () {
@@ -111,7 +120,7 @@ export default {
       getDeviceExcel()
     },
     getMaterialExcel () {
-      this.$refs.materialDialog.show()
+      this.$refs.materialConfigDialog.show()
     },
     getAccountExcel () {
       this.$refs.accountDialog.show()
@@ -130,6 +139,9 @@ export default {
     },
     getOnlineDurationExcel () {
       getOnlineDurationExcel({ type: 'DEVICE_ONLINE_TOTAL' })
+    },
+    getDepartmentOnlineDurationExcel () {
+      this.$refs.onlineDurationDialog.show()
     }
   }
 }

+ 0 - 70
src/views/screen/review/single/components/ReviewAsset.vue

@@ -1,70 +0,0 @@
-<template>
-  <schema-table
-    ref="table"
-    :schema="schema"
-  >
-    <preview-dialog ref="previewDialog" />
-  </schema-table>
-</template>
-
-<script>
-import {
-  State,
-  AssetTypeInfo,
-  AssetTagInfo
-} from '@/constant'
-import {
-  parseByte,
-  getAIState
-} from '@/utils'
-import { addTenantOrOrg } from '@/api/base'
-import {
-  getAssetsByQuery,
-  resolveAsset
-} from '@/api/asset'
-import mixin from './mixin'
-
-export default {
-  name: 'ReviewAsset',
-  mixins: [mixin],
-  data () {
-    return {
-      schema: {
-        list: getAssetsByQuery,
-        transform: this.transformAsset,
-        condition: addTenantOrOrg({ status: State.REVIEW_ASSET }),
-        cols: [
-          { prop: 'tagInfo', type: 'refresh', width: 80 },
-          { prop: 'typeInfo', label: '资源', align: 'center', width: 72 },
-          { prop: 'file', label: '', type: 'asset', on: this.onViewAsset },
-          { prop: 'originalName' },
-          { prop: 'ai', label: 'AI审核', type: 'tag' },
-          { prop: 'size', label: '文件大小', 'align': 'right' },
-          { prop: 'diff', label: '其他', 'align': 'right' },
-          { prop: 'createBy', label: '申请人', 'align': 'right' },
-          { prop: 'createTime', label: '提交时间', 'align': 'right', 'min-width': 100 },
-          { type: 'invoke', width: 160, render: [
-            { label: '查看', on: this.onViewAsset },
-            { label: '通过', on: this.onResolve },
-            { label: '驳回', on: this.onReject }
-          ] }
-        ]
-      }
-    }
-  },
-  methods: {
-    resolve: resolveAsset,
-    transformAsset (asset) {
-      asset.tagInfo = AssetTagInfo[asset.tag]
-      asset.typeInfo = AssetTypeInfo[asset.type]
-      asset.size = parseByte(asset.size)
-      asset.ai = getAIState(asset)
-      asset.createBy = asset.userName || asset.createBy
-      return asset
-    },
-    onViewAsset ({ file }) {
-      this.$refs.previewDialog.show(file)
-    }
-  }
-}
-</script>

+ 0 - 58
src/views/screen/review/single/components/ReviewProgram.vue

@@ -1,58 +0,0 @@
-<template>
-  <schema-table
-    ref="table"
-    :schema="schema"
-  >
-    <material-dialog ref="materialDialog" />
-  </schema-table>
-</template>
-
-<script>
-import { State } from '@/constant'
-import {
-  getProgramsByQuery,
-  resolveProgram
-} from '@/api/program'
-import { addTenantOrOrg } from '@/api/base'
-import mixin from './mixin'
-
-export default {
-  name: 'ReviewProgram',
-  mixins: [mixin],
-  data () {
-    return {
-      schema: {
-        list: getProgramsByQuery,
-        transform: this.transform,
-        condition: addTenantOrOrg({ status: State.SUBMITTED }),
-        cols: [
-          { prop: 'file', label: '缩略图', type: 'asset' },
-          { prop: 'name', label: '节目名称', 'min-width': 100 },
-          { prop: 'createBy', label: '申请人' },
-          { prop: 'createTime', label: '提交时间' },
-          { type: 'invoke', width: 160, render: [
-            { label: '查看', on: this.onView },
-            { label: '通过', on: this.onResolve },
-            { label: '驳回', on: this.onReject }
-          ] }
-        ]
-      }
-    }
-  },
-  methods: {
-    resolve: resolveProgram,
-    transform (program) {
-      program.file = program.img
-        ? {
-          thumb: program.img
-        }
-        : null
-      program.createBy = program.userName || program.createBy
-      return program
-    },
-    onView ({ id }) {
-      this.$refs.materialDialog.showProgram(id)
-    }
-  }
-}
-</script>

+ 0 - 53
src/views/screen/review/single/components/ReviewProgramRecur.vue

@@ -1,53 +0,0 @@
-<template>
-  <schema-table
-    ref="table"
-    :schema="schema"
-  >
-    <material-dialog ref="materialDialog" />
-  </schema-table>
-</template>
-
-<script>
-import {
-  ScheduleType,
-  State
-} from '@/constant'
-import { addTenantOrOrg } from '@/api/base'
-import {
-  getSchedulesByQuery,
-  resolveSchedule
-} from '@/api/calendar'
-import mixin from './mixin'
-
-export default {
-  name: 'ReviewSchedule',
-  mixins: [mixin],
-  data () {
-    return {
-      schema: {
-        list: getSchedulesByQuery,
-        condition: addTenantOrOrg({
-          type: ScheduleType.RECUR,
-          status: State.SUBMITTED
-        }),
-        cols: [
-          { prop: 'name', label: '轮播名称', 'min-width': 100 },
-          { prop: 'createBy', label: '申请人' },
-          { prop: 'createTime', label: '提交时间' },
-          { type: 'invoke', width: 160, render: [
-            { label: '查看', on: this.onView },
-            { label: '通过', on: this.onResolve },
-            { label: '驳回', on: this.onReject }
-          ] }
-        ]
-      }
-    }
-  },
-  methods: {
-    resolve: resolveSchedule,
-    onView ({ id }) {
-      this.$refs.materialDialog.showSchedule(id)
-    }
-  }
-}
-</script>

+ 0 - 53
src/views/screen/review/single/components/ReviewSchedule.vue

@@ -1,53 +0,0 @@
-<template>
-  <schema-table
-    ref="table"
-    :schema="schema"
-  >
-    <material-dialog ref="materialDialog" />
-  </schema-table>
-</template>
-
-<script>
-import {
-  ScheduleType,
-  State
-} from '@/constant'
-import { addTenantOrOrg } from '@/api/base'
-import {
-  getSchedulesByQuery,
-  resolveSchedule
-} from '@/api/calendar'
-import mixin from './mixin'
-
-export default {
-  name: 'ReviewSchedule',
-  mixins: [mixin],
-  data () {
-    return {
-      schema: {
-        list: getSchedulesByQuery,
-        condition: addTenantOrOrg({
-          type: ScheduleType.COMPLEX,
-          status: State.SUBMITTED
-        }),
-        cols: [
-          { prop: 'name', label: '排期名称', 'min-width': 100 },
-          { prop: 'createBy', label: '申请人' },
-          { prop: 'createTime', label: '提交时间' },
-          { type: 'invoke', width: 160, render: [
-            { label: '查看', on: this.onView },
-            { label: '通过', on: this.onResolve },
-            { label: '驳回', on: this.onReject }
-          ] }
-        ]
-      }
-    }
-  },
-  methods: {
-    resolve: resolveSchedule,
-    onView ({ id }) {
-      this.$refs.materialDialog.showSchedule(id)
-    }
-  }
-}
-</script>

+ 0 - 13
src/views/screen/review/single/components/mixin.js

@@ -1,13 +0,0 @@
-export default {
-  methods: {
-    reject () {
-      return Promise.reject()
-    },
-    onResolve (item) {
-      this.resolve(item).then(this.refresh)
-    },
-    onReject (obj) {
-      this.$emit('reject', obj)
-    }
-  }
-}

+ 0 - 147
src/views/screen/review/single/index.vue

@@ -1,147 +0,0 @@
-<template>
-  <wrapper
-    fill
-    margin
-    padding
-    background
-  >
-    <el-tabs
-      v-model="active"
-      class="c-tabs has-bottom-padding"
-    >
-      <el-tab-pane
-        label="资源审核"
-        name="ReviewAsset"
-      />
-      <el-tab-pane
-        label="节目审核"
-        name="ReviewProgram"
-      />
-      <el-tab-pane
-        label="轮播审核"
-        name="ReviewProgramRecur"
-      />
-      <el-tab-pane
-        label="排期审核"
-        name="ReviewSchedule"
-      />
-    </el-tabs>
-    <component
-      :is="active"
-      :key="active"
-      ref="component"
-      @reject="onReject"
-    />
-    <confirm-dialog
-      ref="rejectDialog"
-      title="驳回"
-      @confirm="onConfirmReject"
-    >
-      <div class="c-grid-form u-align-self--center">
-        <span class="c-grid-form__label">审核意见</span>
-        <el-select
-          v-model="review.type"
-          placeholder="请选择"
-        >
-          <el-option
-            v-for="option in reviewOptions"
-            :key="option.label"
-            :label="option.label"
-            :value="option.value"
-          />
-        </el-select>
-        <template v-if="review.type === 'reject'">
-          <span class="c-grid-form__label u-required">原因</span>
-          <el-input
-            v-model.trim="review.reason"
-            type="textarea"
-            placeholder="请填写驳回原因"
-            maxlength="50"
-            :rows="3"
-            resize="none"
-            show-word-limit
-          />
-        </template>
-      </div>
-    </confirm-dialog>
-  </wrapper>
-</template>
-
-<script>
-import { rejectAsset } from '@/api/asset'
-import { rejectProgram } from '@/api/program'
-import { rejectSchedule } from '@/api/calendar'
-import { cancelRequest } from '@/utils/request'
-import ReviewAsset from './components/ReviewAsset'
-import ReviewProgram from './components/ReviewProgram'
-import ReviewProgramRecur from './components/ReviewProgramRecur'
-import ReviewSchedule from './components/ReviewSchedule'
-
-export default {
-  name: 'Review',
-  components: {
-    ReviewAsset,
-    ReviewProgram,
-    ReviewProgramRecur,
-    ReviewSchedule
-  },
-  data () {
-    return {
-      active: 'ReviewAsset',
-      reviewOptions: [
-        { value: 'reject', label: '驳回' },
-        { value: '图文不符' },
-        { value: '内容不合规' }
-      ],
-      review: {
-        type: '',
-        reason: ''
-      }
-    }
-  },
-  computed: {
-    reject () {
-      switch (this.active) {
-        case 'ReviewAsset':
-          return rejectAsset
-        case 'ReviewProgram':
-          return rejectProgram
-        case 'ReviewProgramRecur':
-        case 'ReviewSchedule':
-          return rejectSchedule
-        default:
-          return () => Promise.reject()
-      }
-    }
-  },
-  watch: {
-    active () {
-      cancelRequest()
-    }
-  },
-  methods: {
-    onReject (item) {
-      this.$item = item
-      this.review = {
-        type: 'reject',
-        reason: ''
-      }
-      this.$refs.rejectDialog.show()
-    },
-    onConfirmReject (done) {
-      const reason = this.review.type === 'reject' ? this.review.reason : this.review.type
-      if (!reason) {
-        this.$message({
-          type: 'warning',
-          message: '请选择或填写驳回原因'
-        })
-        return
-      }
-      this.reject(this.$item, reason).then(() => {
-        done()
-        this.$refs.component.$refs.table.decrease(1)
-      })
-    }
-  }
-}
-</script>