Browse Source

feat(camera): record download shortcut

table support auto refresh and adjust some page styles
Casper Dai 2 years ago
parent
commit
0cf8d8d4a5

+ 2 - 0
.env.fujian

@@ -11,4 +11,6 @@ __TAKEOVER__ = 'disabled'
 # 小程序
 __WECHAT__ = 'disabled'
 
+VUE_APP_THUMBNAIL_ORIGIN = 'http://192.168.63.114'
+
 VUE_APP_GAODE_MAP_RANGE = '福建省'

+ 61 - 26
src/components/table/mixins/table.js

@@ -91,6 +91,12 @@ export default {
     },
     paginationConfig () {
       return this.schema.pagination
+    },
+    autoRefreshEachPage () {
+      return this.schema.autoRefreshEachPage
+    },
+    autoRefresh () {
+      return this.schema.autoRefresh || this.autoRefreshEachPage
     }
   },
   watch: {
@@ -118,6 +124,18 @@ export default {
       immediate: true
     }
   },
+  beforeCreate () {
+    this.$refreshTimer = -1
+  },
+  beforeDestroy () {
+    if (this.options) {
+      this.options.death = true
+    }
+    clearTimeout(this.$refreshTimer)
+  },
+  deactivated () {
+    clearTimeout(this.$refreshTimer)
+  },
   activated () {
     if (this.schema.keepalive) {
       this.onPagination()
@@ -150,8 +168,7 @@ export default {
       const options = this.options
       if (!options.loading) {
         options.loading = true
-        const { list, transform } = this.schema
-        list(options.params).then(
+        this.onFetchList(options).then(
           ({ data, totalCount }) => {
             options.loading = false
             options.error = false
@@ -166,6 +183,7 @@ export default {
                 return void this.pageTo(totalCount ? Math.ceil(totalCount / pageSize) : 1)
               }
             }
+            const { transform } = this.schema
             options.list = transform ? data.map(transform) : data
           },
           () => {
@@ -179,6 +197,47 @@ export default {
         })
       }
     },
+    onFetchList (options) {
+      clearTimeout(this.$refreshTimer)
+      const { pageNum } = options.params
+      return this.schema.list(options.params).then(data => {
+        if (this.autoRefresh && !options.death && (this.autoRefreshEachPage || pageNum === 1)) {
+          this.$refreshTimer = setTimeout(this.refreshCurrentPageOnBackground, 5000)
+        }
+        return data
+      })
+    },
+    refreshCurrentPageOnBackground () {
+      const options = this.options
+      if (!options.loading) {
+        this.onFetchList(options).then(
+          ({ data, totalCount }) => {
+            if (!options.loading && !options.death) {
+              options.error = false
+              options.totalCount = totalCount || data.length
+              if (this.isNeedPagination && this.isManualPagination) {
+                const { pageNum, pageSize } = options.params
+                data = data.slice((pageNum - 1) * pageSize, pageNum * pageSize)
+              }
+              if (data.length === 0) {
+                const { pageNum, pageSize } = options.params
+                if (pageNum > 1) {
+                  return void this.pageTo(totalCount ? Math.ceil(totalCount / pageSize) : 1)
+                }
+              }
+              const { transform } = this.schema
+              options.list = transform ? data.map(transform) : data
+              this.$emit('changed', options.list)
+            }
+          },
+          ({ isCancel }) => {
+            if (!isCancel && !options.loading && !options.death) {
+              this.$refreshTimer = setTimeout(this.refreshCurrentPageOnBackground, 2000)
+            }
+          }
+        )
+      }
+    },
     onClickButton ({ on }) {
       if (on) {
         on(this.options.params, this)
@@ -253,30 +312,6 @@ export default {
         return void this.pageTo(options.params.pageNum - 1)
       }
       this.pageTo()
-    },
-    refreshCurrentPageOnBackground () {
-      const options = this.options
-      if (!options.loading) {
-        const { list, transform } = this.schema
-        list(options.params).then(({ data, totalCount }) => {
-          if (!options.loading && !options.death) {
-            options.error = false
-            options.totalCount = totalCount || data.length
-            if (this.isNeedPagination && this.isManualPagination) {
-              const { pageNum, pageSize } = options.params
-              data = data.slice((pageNum - 1) * pageSize, pageNum * pageSize)
-            }
-            if (data.length === 0) {
-              const { pageNum, pageSize } = options.params
-              if (pageNum > 1) {
-                return void this.pageTo(totalCount ? Math.ceil(totalCount / pageSize) : 1)
-              }
-            }
-            options.list = transform ? data.map(transform) : data
-            this.$emit('changed', options.list)
-          }
-        })
-      }
     }
   }
 }

+ 4 - 15
src/views/ad/automation/scheduling/index.vue

@@ -93,15 +93,16 @@ export default {
     return {
       deviceId: '',
       schema: {
+        autoRefresh: true,
+        list: this.getDeviceSchedulings,
+        condition: { order: 'startDate' },
+        transform: this.transform,
         buttons: canEdit
           ? [
             { label: '填充素材包', icon: 'el-icon-edit', on: this.onDataset },
             { label: '一键排单', icon: 'el-icon-edit', on: this.onScheduling }
           ]
           : null,
-        condition: { order: 'startDate' },
-        list: this.getDeviceSchedulings,
-        transform: this.transform,
         filters: [
           { key: 'order', type: 'select', options: [
             { value: 'startDate', label: '日期降序' },
@@ -173,23 +174,11 @@ export default {
       this.$refs.table?.pageTo(1)
     }
   },
-  created () {
-    this.$timer = -1
-  },
-  beforeDestroy () {
-    clearTimeout(this.$timer)
-  },
   methods: {
     onChange ({ id }) {
       this.deviceId = id
     },
     getDeviceSchedulings (params) {
-      clearTimeout(this.$timer)
-      if (params.pageNum === 1) {
-        this.$timer = setTimeout(() => {
-          this.$refs.table.refreshCurrentPageOnBackground()
-        }, 5000)
-      }
       return getDeviceSchedulings({
         deviceId: this.deviceId,
         ...params

+ 1 - 12
src/views/device/camera/index.vue

@@ -78,6 +78,7 @@ export default {
       },
       // 录像
       recordSchema: {
+        autoRefresh: true,
         list: this.getRecords,
         buttons: [
           { type: 'add', label: '新增录像', on: this.onViewSD }
@@ -132,12 +133,6 @@ export default {
       }
     }
   },
-  created () {
-    this.$timer = -1
-  },
-  beforeDestroy () {
-    clearTimeout(this.$timer)
-  },
   methods: {
     isDisableDate (date) {
       return date > Date.now()
@@ -156,12 +151,6 @@ export default {
       this.$refs.recordTableDialog.show()
     },
     getRecords (params) {
-      clearTimeout(this.$timer)
-      if (params.pageNum === 1) {
-        this.$timer = setTimeout(() => {
-          this.$refs.recordTableDialog?.getTable()?.refreshCurrentPageOnBackground()
-        }, 5000)
-      }
       return getRecords({
         identifier: this.identifier,
         ...params

+ 41 - 3
src/views/device/detail/components/DeviceExternal/components/Record/components/PlayAxisDialog/components/PlayAxis.vue

@@ -50,7 +50,22 @@
           :style="{left: leftRate + '%'}"
         />
       </div>
-      <div class="c-table__filters o-time-axis__slecetime">
+      <div class="c-table__filters o-time-axis__selecttime">
+        <div class="o-time-axis__download">
+          <div
+            class="o-button"
+            @click="onStartDownload"
+          >
+            下载
+          </div>
+          <el-input-number
+            v-model="downloadDuration"
+            class="o-time-axis__inputnumber"
+            controls-position="right"
+            :max="15"
+            :min="1"
+          />(分钟)
+        </div>
         <el-date-picker
           v-model="dateValue"
           type="date"
@@ -82,6 +97,7 @@ import { mapGetters } from 'vuex'
 import { GATEWAY_CAMERA_RECORD } from '@/constant'
 import { parseTime } from '@/utils'
 import { isOnline } from '@/api/camera'
+import { downloadRecord } from '@/api/external'
 import playerMixin from '@/components/service/external/player'
 
 export default {
@@ -106,7 +122,8 @@ export default {
       dateValue: parseTime(new Date(), '{y}-{m}-{d}'),
       leftRate: 0,
       disanableWidth: 0,
-      end: ''
+      end: '',
+      downloadDuration: 1
     }
   },
   computed: {
@@ -143,6 +160,18 @@ export default {
     this.end = `${(Number(parseTime(new Date(), '{h}:00').split(':')[0]) + 1).toString().padStart(2, '0')}:00`
   },
   methods: {
+    onStartDownload () {
+      const min = parseInt(this.leftRate * 60 / 100).toString().padStart(2, '0')
+      const startTime = `${this.dateValue} ${this.timeValue.split(':')[0]}:${min}:00`
+      const endTime = parseTime(new Date(Date.parse(startTime) + this.downloadDuration * 60 * 1000), '{y}-{m}-{d} {h}:{i}:{s}')
+      downloadRecord({
+        identifier: this.camera.identifier,
+        startTime,
+        endTime
+      }).then(() => {
+        this.$emit('refreshRecord')
+      })
+    },
     onChange () {
       if (Date.parse(`${this.dateValue} 23:59:59`) < Date.now()) {
         console.log(123)
@@ -277,6 +306,7 @@ export default {
     color: #fff;
     pointer-events: none;
     z-index: 2;
+
     &::after {
       content: "";
       position: absolute;
@@ -314,7 +344,7 @@ export default {
     color: #fff;
   }
 
-  &__slecetime {
+  &__selecttime {
     margin-top: 20px;
   }
 
@@ -333,5 +363,13 @@ export default {
     z-index: 2;
     cursor: not-allowed;
   }
+
+  &__download {
+    color: #fff;
+  }
+
+  &__inputnumber {
+    width: 100px;
+  }
 }
 </style>

+ 5 - 1
src/views/device/detail/components/DeviceExternal/components/Record/components/PlayAxisDialog/index.vue

@@ -8,11 +8,12 @@
     @closed="onClosed"
   >
     <template v-if="contentRender">
-      <PlayAxis
+      <play-axis
         :key="identifier"
         :camera="camera"
         autoplay
         controls
+        @refreshRecord="refreshRecord"
       />
       <i
         class="o-close el-icon-close has-active u-bold"
@@ -54,6 +55,9 @@ export default {
     }
   },
   methods: {
+    refreshRecord () {
+      this.$emit('refreshRecord')
+    },
     show () {
       this.dialogVisible = true
     },

+ 12 - 38
src/views/device/detail/components/DeviceExternal/components/Record/components/RecordPlayer.vue

@@ -8,7 +8,7 @@
       controls
       controlslist="nodownload noremoteplayback"
     />
-    <template v-if="camera.status !== 1">
+    <template v-if="record.status !== 1">
       <div class="o-video__mask">
         <div
           class="l-flex--row center o-video__btn u-pointer"
@@ -19,7 +19,7 @@
       </div>
     </template>
     <div class="l-flex--row c-top">
-      <div class="l-flex__auto c-sibling-item u-ellipsis">{{ camera.startTime }}</div>
+      <div class="l-flex__auto c-sibling-item u-ellipsis">{{ record.startTime }}</div>
       <slot />
       <i
         class="c-sibling-item el-icon-delete has-active"
@@ -36,59 +36,38 @@ import { deleteRecord } from '@/api/external'
 export default {
   name: 'RecordPlayer',
   props: {
-    camera: {
+    record: {
       type: Object,
       required: true
     }
   },
   data () {
     return {
-      paused: true,
-      checked: false,
-      isFullscreen: false,
-      loading: false,
-      isdownload: false
+      isFullscreen: false
     }
   },
   computed: {
     statusIconClass () {
       switch (true) {
-        case this.camera.status === 0:
+        case this.record.status === 0:
           return 'el-icon-download'
-        case this.isdownload:
-          return 'el-icon-download has-active'
-        case this.loading:
-          return 'el-icon-loading'
-        case this.paused:
-          return 'el-icon-video-play has-active'
         default:
-          return 'el-icon-video-pause has-active'
+          return 'el-icon-download has-active'
       }
     },
     assetUrl () {
-      return this.camera.url && getAssetUrl(this.camera.url)
-    }
-  },
-  watch: {
-    camera (newValue, oldValue) {
-      this.paused = newValue.id === oldValue.id ? this.paused : true
-      this.isdownload = (this.camera.status !== 1 && this.camera.status !== 0)
-    }
-  },
-  created () {
-    if (this.camera.status === 0) {
-      this.loading = true
+      return this.record.status === 1 && this.record.url && getAssetUrl(this.record.url)
     }
   },
   methods: {
     onDeleteRecord () {
-      deleteRecord(this.camera.id).then(() => {
-        this.$emit('delRecord')
+      deleteRecord(this.record.id).then(() => {
+        this.$emit('del', this.record)
       })
     },
     onPlayOrPause () {
-      if (this.isdownload) {
-        this.$emit('onResumeDownloadRecord', this.camera.id)
+      if (this.record.status !== 0) {
+        this.$emit('resume', this.record)
       }
     },
     onFullScreen () {
@@ -130,13 +109,8 @@ export default {
   }
 }
 </script>
-<style lang="scss" scoped>
-.c-camera__checkbox {
-  position: absolute;
-  top: 10px;
-  left: 10px;
-}
 
+<style lang="scss" scoped>
 .c-top {
   position: absolute;
   width: 100%;

+ 16 - 23
src/views/device/detail/components/DeviceExternal/components/Record/index.vue

@@ -12,7 +12,9 @@
       <div
         v-if="cameras.length===0"
         class="u-color--info l-flex--col center"
-      >暂无数据</div>
+      >
+        暂无数据
+      </div>
       <div v-else>
         <div
           v-for="(camera, index) in cameras"
@@ -28,17 +30,18 @@
               class="c-camera__bound"
               :style="{color: index === active ? '#fff':'#4293FE'}"
             >
-              <div
+              <i
                 class="c-camera__dian"
                 :style="{backgroundColor: index === active ? '#fff':'#4293FE'}"
-              />{{ camera.bound ? '已使用' : '未使用' }}
+              />
+              {{ camera.bound ? '已使用' : '未使用' }}
             </div>
             <!-- <div :style="{color: index === 2 ? '#E51414':'#8E929C'}">已下载{{ camera.totalCount }}个录像</div> -->
           </div>
           <div
             class="c-camera__tip"
-            :style="{backgroundColor: camera.onlineStatus===1?'#04A681':'#E51414'}"
-          >{{ camera.onlineStatus===1?'在线':'离线' }}</div>
+            :style="{ backgroundColor: camera.onlineStatus === 1 ? '#04A681' : '#E51414' }"
+          >{{ camera.onlineStatus === 1 ? '在线' : '离线' }}</div>
         </div>
       </div>
     </div>
@@ -50,9 +53,10 @@
       >
         <grid-table-item v-slot="item">
           <record-player
-            :camera="item"
-            @delRecord="onDeleteRecord"
-            @onResumeDownloadRecord="onResumeDownloadRecord"
+            :key="item.id"
+            :record="item"
+            @del="onDeleteRecord"
+            @resume="onResumeDownloadRecord"
           />
         </grid-table-item>
       </grid-table>
@@ -73,6 +77,7 @@
       ref="playAxisDialog"
       :camera="cameraObj"
       :identifier="identifier"
+      @refreshRecord="onDeleteRecord"
     />
   </div>
 </template>
@@ -107,6 +112,7 @@ export default {
       searchName: '',
       active: 0,
       recordSchema: {
+        autoRefresh: true,
         pageSize: 6,
         list: this.getRecords,
         buttons: [
@@ -156,12 +162,6 @@ export default {
       this.$refs.table?.pageTo(1)
     }
   },
-  created () {
-    this.$timer = -1
-  },
-  beforeDestroy () {
-    clearTimeout(this.$timer)
-  },
   methods: {
     onPlayBack () {
       if (this.cameras[this.active].onlineStatus === 1) {
@@ -193,14 +193,7 @@ export default {
       this.identifier = identifier
       this.$refs.recordTableDialog.show()
     },
-    // 获取录像
     getRecords (params) {
-      clearTimeout(this.$timer)
-      if (params.pageNum === 1) {
-        this.$timer = setTimeout(() => {
-          this.$refs.table?.refreshCurrentPageOnBackground()
-        }, 5000)
-      }
       return getRecords({
         cameraId: this.cameraId,
         ...params
@@ -209,14 +202,14 @@ export default {
     onDeleteRecord () {
       this.$refs.table?.pageTo(1)
     },
-    onResumeDownloadRecord (id) {
+    onResumeDownloadRecord ({ id }) {
       resumeDownloadRecord(id).then(() => {
         this.$refs.table?.pageTo(1)
       })
     },
     onStopDownloadRecord () {
       stopDownloadRecord(this.identifier).then(() => {
-        this.$refs.recordTableDialog.getTable().pageTo(1)
+        this.$refs.table?.pageTo(1)
       })
     },
     onPlayRecord ({ url }) {

+ 1 - 0
src/views/device/index.vue

@@ -29,6 +29,7 @@ export default {
     return {
       schema: {
         keepalive: true,
+        autoRefreshEachPage: true,
         list: this.getDevicesByQuery,
         filters: [
           { key: 'name', type: 'search', placeholder: '设备名称' },

+ 14 - 10
src/views/external/box/components/Device.vue

@@ -153,13 +153,15 @@ export default {
           __SUB_DEVICE__
             ? { label: '设备名称', render: (data, h) => data.empty ? h('span', { staticClass: 'u-color--info' }, '暂无备份设备') : data.name, 'min-width': 120 }
             : { prop: 'name', label: '设备名称', 'min-width': 120 },
-          { label: '型号', render: (data, h) => h('edit-input', {
-            props: {
-              value: data.remark,
-              placeholder: '-'
-            },
-            on: { edit: val => this.onEditRemark(data, val) }
-          }), 'class-name': 'c-edit-column' },
+          { label: '型号', render: (data, h) => data.empty
+            ? ''
+            : h('edit-input', {
+              props: {
+                value: data.remark,
+                placeholder: '-'
+              },
+              on: { edit: val => this.onEditRemark(data, val) }
+            }), 'class-name': 'c-edit-column' },
           { prop: 'productName', label: '配置' },
           { prop: 'serialNumber', label: '序列号', 'min-width': 140 },
           { prop: 'mac', label: 'MAC', 'min-width': 140 },
@@ -173,9 +175,11 @@ export default {
                   : { type: 'danger', label: '离线' }
               : { type: 'warning', label: '未激活' },
             on: this.onTagClick },
-          { label: '使用情况', type: 'tag', render: ({ bound }) => bound
-            ? { type: 'success', label: '已使用' }
-            : { type: 'primary', label: '未使用' } },
+          { label: '使用情况', type: 'tag', render: ({ empty, bound }) => empty
+            ? null
+            : bound
+              ? { type: 'success', label: '已使用' }
+              : { type: 'primary', label: '未使用' } },
           { type: 'invoke', render: [
             { label: '配置', render: ({ isMaster }) => isMaster, on: this.onSettingDevice },
             __SUB_DEVICE__ && { label: '添加备份', render: ({ isMaster }) => isMaster, on: this.onAddSubDevice },

+ 2 - 16
src/views/external/camera/snap/index.vue

@@ -155,7 +155,8 @@ export default {
     },
     snapSchema () {
       return {
-        list: this.getSnapPicResults,
+        autoRefresh: true,
+        list: getSnapPicResults,
         condition: { cameraId: this.cameraId },
         cols: [
           { prop: 'file', type: 'asset', on: this.onViewAsset, refresh: true },
@@ -181,12 +182,6 @@ export default {
       }
     }
   },
-  created () {
-    this.$timer = -1
-  },
-  beforeDestroy () {
-    clearTimeout(this.$timer)
-  },
   methods: {
     onEditRemark (camera, { newVal, oldVal }) {
       if (newVal === oldVal) {
@@ -244,15 +239,6 @@ export default {
       this.cameraId = camera.id
       this.$refs.resultDialog.show()
     },
-    getSnapPicResults (params) {
-      clearTimeout(this.$timer)
-      if (params.pageNum === 1) {
-        this.$timer = setTimeout(() => {
-          this.$refs.resultDialog?.getTable()?.refreshCurrentPageOnBackground()
-        }, 10000)
-      }
-      return getSnapPicResults(params)
-    },
     onViewAsset ({ file }) {
       this.$refs.previewDialog.show(file)
     }

+ 1 - 12
src/views/realm/ai/ai-timing/index.vue

@@ -69,6 +69,7 @@ export default {
     },
     historySchema () {
       return {
+        autoRefresh: true,
         list: this.getHistory,
         transform: this.transform,
         filters: [
@@ -87,20 +88,8 @@ export default {
       }
     }
   },
-  created () {
-    this.$timer = -1
-  },
-  beforeDestroy () {
-    clearTimeout(this.$timer)
-  },
   methods: {
     getHistory (params) {
-      clearTimeout(this.$timer)
-      if (params.pageNum === 1) {
-        this.$timer = setTimeout(() => {
-          this.$refs.historyDialog?.getTable()?.refreshCurrentPageOnBackground()
-        }, 10000)
-      }
       return getHistory({
         deviceId: this.device ? this.device.id : void 0,
         ...params

+ 1 - 1
src/views/screen/review/workflow/components/WorkflowHistoryDialog.vue

@@ -21,7 +21,7 @@ export default {
         cols: [
           { label: '节点', render: ({ status }) => WorkflowStateInfo[status], width: 100, align: 'center' },
           { prop: 'handledBy', label: '处理人', width: 160, align: 'center' },
-          { prop: 'createTime', label: '处理时间', align: 'center' },
+          { prop: 'createTime', label: '提交时间', align: 'center' },
           { prop: 'reason', label: '备注', align: 'right' }
         ]
       }