소스 검색

feat: set the playback duration of pictures in batches

Casper Dai 2 년 전
부모
커밋
4d168dbbef

+ 51 - 18
src/components/dialog/MultiAssetTransferDialog/index.vue

@@ -95,22 +95,44 @@
             class="l-flex__auto l-flex--row center"
             description="请添加资源"
           />
-          <draggable
-            v-else
-            v-model="assets"
-            class="l-flex__auto l-flex--col u-font-size--sm u-overflow-y--auto"
-            handle=".mover"
-            animation="300"
-          >
-            <draggable-item
-              v-for="(asset, index) in assets"
-              :key="asset.key"
-              :item="asset"
-              :hide-duration="hideDuration"
-              @view="onViewAsset"
-              @del="onDelAsset(index)"
-            />
-          </draggable>
+          <template v-else>
+            <div
+              v-if="options.durationEditable"
+              class="l-flex__none l-flex--row right c-sibling-item--v"
+            >
+              <div class="c-sibling-item u-color--info u-font-size--sm">图片统一上播时长(s)</div>
+              <el-input-number
+                v-model="duration"
+                class="c-sibling-item u-width--xs"
+                title="上播时长(s)"
+                controls-position="right"
+                :min="1"
+                :max="86400"
+                step-strictly
+              />
+              <div
+                class="c-sibling-item near o-button"
+                @click="onSetImageDuration"
+              >
+                设置
+              </div>
+            </div>
+            <draggable
+              v-model="assets"
+              class="l-flex__auto l-flex--col c-sibling-item--v u-font-size--sm u-overflow-y--auto"
+              handle=".mover"
+              animation="300"
+            >
+              <draggable-item
+                v-for="(asset, index) in assets"
+                :key="asset.key"
+                :item="asset"
+                :hide-duration="hideDuration"
+                @view="onViewAsset"
+                @del="onDelAsset(index)"
+              />
+            </draggable>
+          </template>
         </div>
       </div>
     </template>
@@ -158,7 +180,9 @@ export default {
       directoryOption: null,
       fileDir: null,
       assets: [],
-      tableAssets: []
+      tableAssets: [],
+      duration: 10,
+      options: {}
     }
   },
   computed: {
@@ -216,7 +240,7 @@ export default {
     show (assets, options) {
       const { types, directory, ...data } = {
         types: [AssetType.IMAGE, AssetType.VIDEO, AssetType.STREAMING_MEDIA],
-        duration: 5,
+        duration: 10,
         durationEditable: true,
         ...options
       }
@@ -384,6 +408,15 @@ export default {
       } else {
         done()
       }
+    },
+    onSetImageDuration () {
+      const duration = this.duration
+      this.assets.forEach(asset => {
+        const { type, disabled } = asset
+        if (!disabled && type === AssetType.IMAGE) {
+          asset.duration = duration
+        }
+      })
     }
   }
 }

+ 10 - 4
src/components/service/EventTargetPicker/index.vue

@@ -1,12 +1,15 @@
 <template>
   <div class="l-flex--col">
     <div class="c-sibling-item--v has-bottom-padding--sm has-bottom-border">
-      <div class="c-sibling-item--v u-bold">
-        <span class="c-sibling-item u-font-size--sm">上播内容</span>
+      <div
+        class="l-flex--row inline c-sibling-item--v u-font-size--sm u-bold"
+        :class="{ 'has-active': isAssets }"
+        @click="onEditAssets"
+      >
+        <span class="c-sibling-item">上播内容</span>
         <i
           v-if="isAssets"
-          class="c-sibling-item el-icon-edit u-color--blue has-active"
-          @click="onEditAssets"
+          class="c-sibling-item near el-icon-edit"
         />
       </div>
       <div
@@ -308,6 +311,9 @@ export default {
       this.$refs.previewDialog.show(file)
     },
     onEditAssets () {
+      if (!this.isAssets) {
+        return
+      }
       this.$refs.transferDialog.show(this.currentTarget.assets)
     },
     onSaveAssets (assets) {

+ 8 - 0
src/scss/bem/_layout.scss

@@ -35,6 +35,14 @@
   &.center {
     justify-content: center;
   }
+
+  &.right {
+    justify-content: flex-end;
+  }
+
+  &.inline {
+    display: inline-flex
+  }
 }
 
 .l-flex--col {

+ 2 - 0
src/utils/index.js

@@ -270,6 +270,8 @@ export function transformContractAssetToDraggableAsset ({ id, keyName, duration,
     return {
       id,
       keyName,
+      tag,
+      type,
       duration,
       key: id,
       disabled: type === AssetType.VIDEO,

+ 86 - 51
src/views/ad/automation/contract/index.vue

@@ -29,7 +29,7 @@
     <confirm-dialog
       ref="editDialog"
       :title="contractName"
-      size="lg fixed"
+      size="xl fixed"
       @confirm="onSaveEdit"
     >
       <div class="l-flex__fill l-flex c-step">
@@ -79,13 +79,9 @@
               </template>
               <div class="c-grid-form__label">上播时长(s)</div>
               <el-input-number
-                v-model="contract.duration"
-                class="has-info"
-                data-info="范围:1~86400"
+                :value="totalDuration"
                 controls-position="right"
-                :min="1"
-                :max="86400"
-                step-strictly
+                disabled
               />
               <div class="c-grid-form__label">上播次数</div>
               <el-input-number
@@ -129,28 +125,19 @@
           </div>
         </div>
         <div class="l-flex__fill l-flex--col c-step__column">
-          <div class="l-flex--row c-contract-dialog__header u-color--black u-font-size--sm has-bottom-border">
+          <div
+            class="l-flex--row inline c-contract-dialog__header u-align-self--start u-color--black u-font-size--sm u-bold has-bottom-border has-active"
+            @click="onEditAssets"
+          >
             <span class="c-sibling-item u-bold">上播内容</span>
-            <i
-              class="c-sibling-item near el-icon-edit u-color--blue has-active"
-              @click="onEditAssets"
-            />
+            <i class="c-sibling-item near el-icon-edit" />
           </div>
-          <draggable
-            v-model="assets"
-            class="l-flex__fill u-overflow-y--auto"
-            handle=".mover"
-            animation="300"
-          >
-            <draggable-item
-              v-for="(asset, index) in assets"
-              :key="asset.key"
-              :item="asset"
-              :hide-duration="hideDuration"
-              @view="onViewAsset"
-              @del="onDelAsset(index)"
-            />
-          </draggable>
+          <schema-table
+            ref="assetContentTable"
+            :schema="assetSchema"
+            @row-click="onAssetRowClick"
+            @selection-change="onAssetSelectionChange"
+          />
         </div>
       </div>
     </confirm-dialog>
@@ -168,7 +155,9 @@
 <script>
 import {
   TimeType,
-  SCREEN_TIME_KEY
+  SCREEN_TIME_KEY,
+  AssetTagInfo,
+  AssetTypeInfo
 } from '@/constant'
 import {
   parseTime,
@@ -194,13 +183,9 @@ import {
   bindFileToContract,
   deleteFileFromContract
 } from './api'
-import Draggable from 'vuedraggable'
 
 export default {
   name: 'AdContract',
-  components: {
-    Draggable
-  },
   data () {
     return {
       schema: {
@@ -238,6 +223,24 @@ export default {
         ]
       },
       files: [],
+      assetSchema: {
+        nonPagination: true,
+        list: this.getAssetsByDataset,
+        buttons: [
+          { type: 'del', label: '移除', on: this.onDelAssets }
+        ],
+        cols: [
+          { type: 'selection' },
+          { prop: 'tagInfo', label: '类型', width: 80, align: 'center' },
+          { prop: 'typeInfo', label: '资源', width: 72, align: 'center' },
+          { prop: 'file', label: '', type: 'asset', on: this.onViewAsset },
+          { prop: 'name', label: '' },
+          { prop: 'durationInfo', label: '上播时长', width: 100, align: 'center' },
+          { type: 'invoke', render: [
+            { label: '移除', on: this.onDelAsset }
+          ] }
+        ]
+      },
       assets: []
     }
   },
@@ -245,8 +248,8 @@ export default {
     contractName () {
       return this.contract?.name
     },
-    hideDuration () {
-      return this.assets.length <= 1
+    totalDuration () {
+      return this.assets.reduce((total, { duration }) => total + Number(duration), 0)
     }
   },
   methods: {
@@ -321,7 +324,7 @@ export default {
       return transformContractAssetToDraggableAsset(asset)
     },
     onSaveEdit (done) {
-      const { date, time, duration, count } = this.contract
+      const { date, time, count } = this.contract
       const { startTime, endTime } = transformToTaskTime(time)
       if (!startTime) {
         this.$message({
@@ -342,19 +345,17 @@ export default {
         day: calculateDay(date[0], date[1]) + 1,
         startTime,
         endTime,
-        duration,
+        duration: this.totalDuration,
         count
       }
       const data = {}
       if (['startDate', 'day', 'startTime', 'endTime', 'duration', 'count'].some(key => attrs[key] !== this.$contract[key])) {
         data.attrs = attrs
       }
-      let totalDuration = 0
       const delIdMap = {
         ...this.$assetMap
       }
       const assets = this.assets.map(({ id, keyName, duration }, index) => {
-        totalDuration += duration
         const data = {
           keyName,
           duration,
@@ -380,16 +381,6 @@ export default {
       if (delIds.length > 0) {
         data.deleteIds = delIds
       }
-      if (this.assets.length > 1 && totalDuration % duration !== 0) {
-        this.$confirm(
-          '上播时长与上播内容总时长不一致,上播内容无法完整播放',
-          '继续保存',
-          { type: 'warning' }
-        ).then(() => {
-          this.updateContract(data, done)
-        })
-        return
-      }
       this.updateContract(data, done)
     },
     updateContract (data, done) {
@@ -409,11 +400,9 @@ export default {
     },
     onSaveAssets (assets) {
       this.assets = assets
+      this.onAssetChanged()
       return Promise.resolve()
     },
-    onDelAsset (index) {
-      this.assets.splice(index, 1)
-    },
     onChange ({ raw }) {
       this.$refs.upload.clearFiles()
       bindFileToContract(this.$contract.id, raw).then(({ data }) => {
@@ -458,6 +447,52 @@ export default {
     },
     onSelectionChange (val) {
       this.$selectionItems = val
+    },
+    getAssetsByDataset () {
+      this.$selectionAssetItems = null
+      return Promise.resolve({ data: this.assets.map(({ key, tag, type, file, name, duration }) => {
+        return {
+          key,
+          tagInfo: AssetTagInfo[tag],
+          typeInfo: AssetTypeInfo[type],
+          file,
+          name,
+          durationInfo: parseDuration(duration)
+        }
+      }) })
+    },
+    onAssetChanged () {
+      this.$refs.assetContentTable.pageTo()
+    },
+    onAssetRowClick (row) {
+      this.$refs.assetContentTable.getInst().toggleRowSelection(row)
+    },
+    onAssetSelectionChange (val) {
+      this.$selectionAssetItems = val
+    },
+    onDelAsset (asset, index) {
+      this.assets.splice(index, 1)
+      this.onAssetChanged()
+    },
+    onDelAssets () {
+      if (this.$selectionAssetItems?.length) {
+        this.$confirm(
+          '移除所选资源?',
+          '操作确认',
+          { type: 'warning' }
+        ).then(() => {
+          this.$selectionAssetItems.forEach(({ key }) => {
+            const index = this.assets.find(asset => asset.key === key)
+            this.assets.splice(index, 1)
+          })
+          this.onAssetChanged()
+        })
+      } else {
+        this.$message({
+          type: 'warning',
+          message: '请选择需移除的资源'
+        })
+      }
     }
   }
 }

+ 1 - 1
src/views/screen/material/program/ast/Designer.vue

@@ -602,7 +602,7 @@ export default {
               {
                 types: attr.options.type,
                 directory: this.directoryOption,
-                duration: this.widget.interval || 5,
+                duration: this.widget.interval || 10,
                 durationEditable: !this.widget.sameInterval
               }
             )

+ 1 - 1
src/views/screen/material/program/ast/core/config-json/base.js

@@ -217,7 +217,7 @@ export const animationConfig = {
 
 export const intervalConfig = {
   props: {
-    interval: 5,
+    interval: 10,
     sameInterval: 1
   },
   options: [