Selaa lähdekoodia

feat: automatic scheduling

Casper Dai 3 vuotta sitten
vanhempi
sitoutus
c295ce46c0

+ 34 - 1
src/views/ad/api.js

@@ -1,7 +1,8 @@
 import request from '@/utils/request'
 import {
   resolve,
-  reject
+  reject,
+  send
 } from '@/api/base'
 
 export function getOrders (query, options) {
@@ -36,6 +37,14 @@ export function rejectOrder ({ id }, reason) {
   })
 }
 
+export function getOrderDetail (id) {
+  return send({
+    url: `/ad/tenant/order/detail`,
+    method: 'GET',
+    params: { id }
+  })
+}
+
 export function getAssets (query, options) {
   const { pageNum: pageIndex, pageSize, ...params } = query
   return request({
@@ -81,6 +90,17 @@ export function getOrdersByDevice (query, options) {
   })
 }
 
+export function createScheduling (deviceIds, data) {
+  return send({
+    url: '/ad/tenant/order/scheduling',
+    method: 'POST',
+    data: {
+      deviceIds,
+      ...data
+    }
+  })
+}
+
 export function getDeviceSchedulings (query, options) {
   const { pageNum: pageIndex, pageSize, ...params } = query
   return request({
@@ -93,3 +113,16 @@ export function getDeviceSchedulings (query, options) {
     }
   })
 }
+
+export function getDeviceScheduling (query, options) {
+  const { pageNum: pageIndex, pageSize, ...params } = query
+  return request({
+    url: '/ad/tenant/order/scheduling/detail',
+    method: 'GET',
+    params: {
+      pageIndex, pageSize,
+      ...params,
+      ...options
+    }
+  })
+}

+ 5 - 5
src/views/ad/history/index.vue

@@ -60,12 +60,12 @@ export default {
         list: this.getSources,
         cols: [
           { prop: 'file', label: '缩略图', type: 'asset', on: this.onViewAsset },
-          { prop: 'adDuration', label: '播放时长', align: 'left' },
           { prop: 'fileType', label: '文件类型', align: 'center' },
-          { prop: 'size', label: '文件大小' },
-          { prop: 'ratio', label: '分辨率' },
-          { prop: 'remark', label: '其他' },
-          { type: 'invoke', render: [
+          { prop: 'adDuration', label: '播放时长', align: 'right' },
+          { prop: 'size', label: '文件大小', align: 'right' },
+          { prop: 'ratio', label: '分辨率', align: 'right' },
+          { prop: 'remark', label: '其他', align: 'right' },
+          { type: 'invoke', width: 80, render: [
             { label: '查看', render ({ file }) { return !!file }, on: this.onViewSource }
           ] }
         ]

+ 4 - 4
src/views/ad/review-asset/index.vue

@@ -73,10 +73,10 @@ export default {
           { type: 'refresh' },
           { prop: 'file', label: '缩略图', type: 'asset', on: this.onView },
           { prop: 'fileType', label: '文件类型', align: 'center' },
-          { prop: 'size', label: '文件大小' },
-          { prop: 'ratio', label: '分辨率' },
-          { prop: 'remark', label: '其他' },
-          { prop: 'createTime', label: '提交时间' },
+          { prop: 'size', label: '文件大小', align: 'right' },
+          { prop: 'ratio', label: '分辨率', align: 'right' },
+          { prop: 'remark', label: '其他', align: 'right' },
+          { prop: 'createTime', label: '提交时间', align: 'right', 'min-width': 120 },
           { type: 'invoke', width: 160, render: [
             { label: '查看', on: this.onViewAsset },
             { label: '通过', on: this.onResolve },

+ 6 - 6
src/views/ad/review-order/index.vue

@@ -101,13 +101,13 @@ export default {
         list: this.getSources,
         cols: [
           { prop: 'file', label: '缩略图', type: 'asset', on: this.onViewAsset },
-          { prop: 'adDuration', label: '播放时长', align: 'left' },
           { prop: 'fileType', label: '文件类型', align: 'center' },
-          { prop: 'size', label: '文件大小' },
-          { prop: 'ratio', label: '分辨率' },
-          { prop: 'remark', label: '其他' },
-          { prop: 'statusTag', type: 'tag' },
-          { type: 'invoke', render: [
+          { prop: 'adDuration', label: '播放时长', align: 'right' },
+          { prop: 'size', label: '文件大小', align: 'right' },
+          { prop: 'ratio', label: '分辨率', align: 'right' },
+          { prop: 'remark', label: '其他', align: 'right' },
+          { prop: 'statusTag', type: 'tag', align: 'center', width: 120 },
+          { type: 'invoke', width: 80, render: [
             { label: '查看', render ({ file }) { return !!file }, on: this.onViewSource }
           ] }
         ]

+ 133 - 5
src/views/ad/scheduling/index.vue

@@ -17,17 +17,54 @@
       row-key="id"
       :schema="schema"
     />
+    <table-dialog
+      ref="tableDialog"
+      :title="title"
+      :schema="schedulingSchema"
+    />
+    <table-dialog
+      ref="adDialog"
+      title="广告内容"
+      :schema="adSchema"
+    />
   </wrapper>
 </template>
 
 <script>
-import { getDeviceSchedulings } from '../api'
+import { AssetType } from '@/constant'
+import {
+  parseTime,
+  parseByte,
+  parseDuration
+} from '@/utils'
+import {
+  createScheduling,
+  getDeviceSchedulings,
+  getDeviceScheduling,
+  getOrderDetail
+} from '../api'
 
 export default {
   name: 'AdScheduling',
   data () {
     return {
-      deviceId: ''
+      deviceId: '',
+      schedulingId: '',
+      title: '',
+      adSchema: {
+        list: this.getSources,
+        cols: [
+          { prop: 'file', label: '缩略图', type: 'asset', on: this.onViewAsset },
+          { prop: 'fileType', label: '文件类型', align: 'center' },
+          { prop: 'adDuration', label: '播放时长', align: 'right' },
+          { prop: 'size', label: '文件大小', align: 'right' },
+          { prop: 'ratio', label: '分辨率', align: 'right' },
+          { prop: 'remark', label: '其他', align: 'right' },
+          { type: 'invoke', width: 80, render: [
+            { label: '查看', render ({ file }) { return !!file }, on: this.onViewSource }
+          ] }
+        ]
+      }
     }
   },
   computed: {
@@ -38,7 +75,29 @@ export default {
         ],
         condition: { deviceId: this.deviceId },
         list: getDeviceSchedulings,
-        cols: [{ prop: 'name', label: '名称', align: 'center' }]
+        transform: this.transform,
+        cols: [
+          { type: 'refresh' },
+          { prop: 'startDate', label: '日期' },
+          { prop: 'createTime', label: '生成时间' },
+          { prop: 'statusTag', type: 'tag', align: 'center' },
+          { type: 'invoke', render: [
+            { label: '详情', on: this.onView }
+          ] }
+        ]
+      }
+    },
+    schedulingSchema () {
+      return {
+        condition: { id: this.schedulingId },
+        list: getDeviceScheduling,
+        transform: this.transformScheduling,
+        cols: [
+          { prop: 'time', label: '时间', 'align': 'center' },
+          { type: 'invoke', render: [
+            { label: '内容', on: this.onViewOrder }
+          ] }
+        ]
       }
     }
   },
@@ -46,8 +105,77 @@ export default {
     onChange (deviceId) {
       this.deviceId = deviceId
     },
-    onScheduling (val) {
-      console.log(val)
+    onScheduling () {
+      const startDate = parseTime(new Date(), '{y}-{m}-{d}')
+      createScheduling([this.deviceId], {
+        startDate,
+        endDate: startDate
+      }).then(() => {
+        this.$refs.table.pageTo()
+      })
+    },
+    transform (scheduling) {
+      const { status } = scheduling
+      scheduling.statusTag = {
+        label: ['生成中', '待发布', '已发布'][status],
+        type: ['primary', 'warning', 'success'][status]
+      }
+      return scheduling
+    },
+    onView ({ id, startDate }) {
+      this.title = startDate
+      this.schedulingId = id
+      this.$refs.tableDialog.show()
+    },
+    transformScheduling ({ id, orderId, startTime, endTime }) {
+      return {
+        id,
+        orderId,
+        time: `${startTime}-${endTime}`
+      }
+    },
+    onViewOrder ({ orderId }) {
+      getOrderDetail(orderId).then(({ data }) => {
+        this.$order = data
+        this.$refs.adDialog.show()
+      })
+    },
+    getSources () {
+      const sources = this.$order.assets
+      return Promise.resolve({
+        data: sources.map(this.transformSource),
+        totalCount: sources.length
+      })
+    },
+    transformSource ({ keyName, type, adDuration, duration, size, width, height, thumb }) {
+      const isImage = type === AssetType.IMAGE
+      return type
+        ? {
+          file: {
+            type,
+            url: keyName,
+            thumbnail: isImage ? keyName : thumb || null,
+            origin: !isImage
+          },
+          fileType: isImage ? '图片' : '视频',
+          adDuration: parseDuration(adDuration || duration),
+          ratio: width && height ? `${width}x${height}` : '-',
+          size: parseByte(size),
+          remark: duration ? parseDuration(duration) : '-'
+        }
+        : {
+          fileType: '-',
+          adDuration: parseDuration(adDuration || duration),
+          ratio: '-',
+          size: '-',
+          remark: '素材已删除'
+        }
+    },
+    onViewSource ({ file }) {
+      this.onViewAsset(file)
+    },
+    onViewAsset (asset) {
+      this.$refs.previewDialog.show(asset)
     }
   }
 }

+ 94 - 4
src/views/ad/task/index.vue

@@ -17,31 +17,121 @@
       row-key="id"
       :schema="schema"
     />
+    <table-dialog
+      ref="adDialog"
+      title="广告内容"
+      :schema="adSchema"
+    />
   </wrapper>
 </template>
 
 <script>
-import { getOrdersByDevice } from '../api'
+import {
+  State,
+  AssetType
+} from '@/constant'
+import {
+  parseByte,
+  parseDuration
+} from '@/utils'
+import {
+  getOrdersByDevice,
+  getOrderDetail
+} from '../api'
 
 export default {
   name: 'AdOrderTask',
   data () {
     return {
-      deviceId: ''
+      deviceId: '',
+      adSchema: {
+        list: this.getSources,
+        cols: [
+          { prop: 'file', label: '缩略图', type: 'asset', on: this.onViewAsset },
+          { prop: 'fileType', label: '文件类型', align: 'center' },
+          { prop: 'adDuration', label: '播放时长', align: 'right' },
+          { prop: 'size', label: '文件大小', align: 'right' },
+          { prop: 'ratio', label: '分辨率', align: 'right' },
+          { prop: 'remark', label: '其他', align: 'right' },
+          { type: 'invoke', width: 80, render: [
+            { label: '查看', render ({ file }) { return !!file }, on: this.onViewSource }
+          ] }
+        ]
+      }
     }
   },
   computed: {
     schema () {
       return {
-        condition: { deviceId: this.deviceId },
+        condition: { deviceId: this.deviceId, orderStatus: State.RESOLVED },
         list: getOrdersByDevice,
-        cols: [{ prop: 'name', label: '名称', align: 'center' }]
+        transform: this.transform,
+        cols: [
+          { type: 'refresh' },
+          { prop: 'startDate', label: '起始日期' },
+          { prop: 'range', label: '时段' },
+          { prop: 'freq', label: '频率' },
+          { type: 'invoke', render: [
+            { label: '内容', on: this.onView }
+          ] }
+        ]
       }
     }
   },
   methods: {
     onChange (deviceId) {
       this.deviceId = deviceId
+    },
+    transform ({ orderId, startDate, startTime, endTime, day, duration, count }) {
+      return {
+        orderId,
+        startDate,
+        range: `${startTime}-${endTime}`,
+        freq: `${day}天 x ${duration}秒 x ${count}次`
+      }
+    },
+    onView ({ orderId }) {
+      getOrderDetail(orderId).then(({ data }) => {
+        this.$order = data
+        this.$refs.adDialog.show()
+      })
+    },
+    getSources () {
+      const sources = this.$order.assets
+      return Promise.resolve({
+        data: sources.map(this.transformSource),
+        totalCount: sources.length
+      })
+    },
+    transformSource ({ keyName, type, adDuration, duration, size, width, height, thumb }) {
+      const isImage = type === AssetType.IMAGE
+      return type
+        ? {
+          file: {
+            type,
+            url: keyName,
+            thumbnail: isImage ? keyName : thumb || null,
+            origin: !isImage
+          },
+          fileType: isImage ? '图片' : '视频',
+          adDuration: parseDuration(adDuration || duration),
+          ratio: width && height ? `${width}x${height}` : '-',
+          size: parseByte(size),
+          remark: duration ? parseDuration(duration) : '-'
+        }
+        : {
+          fileType: '-',
+          adDuration: parseDuration(adDuration || duration),
+          ratio: '-',
+          size: '-',
+          remark: '素材已删除'
+        }
+    },
+    onViewSource ({ file }) {
+      this.onViewAsset(file)
+    },
+    onViewAsset (asset) {
+      this.$refs.previewDialog.show(asset)
     }
   }
 }