瀏覽代碼

fix: ratio deploy

Casper Dai 2 年之前
父節點
當前提交
83f1c8107f

+ 3 - 2
src/api/device.js

@@ -222,7 +222,7 @@ export function deleteProductType ({ id, name }) {
   }, name)
 }
 
-export function getProductTypes (query) {
+export function getProductTypes (query, options) {
   const { pageNum: pageIndex, pageSize, ...params } = query
   return tenantRequest({
     url: '/productType/list',
@@ -230,7 +230,8 @@ export function getProductTypes (query) {
     params: addTenant({
       pageIndex, pageSize,
       ...params
-    })
+    }),
+    ...options
   })
 }
 

+ 1 - 4
src/utils/mqtt.js

@@ -31,12 +31,9 @@ const whiteList = [
     val: WillTopic
   }, {
     type: 'topic',
-    val: /^\d+\/\d+\/(status|screenshot|restart)/
+    val: /^\d+\/\d+\/(status|screenshot|restart|plc)/
   }, {
     val: /messageId/
-  }, {
-    type: 'topic',
-    val: /^plc/
   }
 ]
 

+ 0 - 677
src/views/device/timeline/bak.vue

@@ -1,677 +0,0 @@
-<template>
-  <wrapper
-    auto
-    margin
-    padding
-    background
-  >
-    <div class="l-flex__none l-flex c-device-detail has-bottom-padding">
-      <div
-        class="l-flex__none c-device-detail__screen o-program"
-        :class="{ 'u-pointer': programProxy }"
-        :style="programStyle"
-        @click="onView"
-      />
-      <div class="l-flex__auto l-flex--col">
-        <div class="l-flex__none c-device-detail__name u-ellipsis">{{ deivceName }}</div>
-        <template v-if="programProxy">
-          <div class="l-flex__none c-device-detail__program u-ellipsis">
-            <span
-              class="u-pointer"
-              @click="onView"
-            >
-              {{ programName }}
-            </span>
-          </div>
-          <div class="l-flex__none c-device-detail__time">{{ programTime }}</div>
-        </template>
-      </div>
-    </div>
-    <div
-      v-loading="deviceOptions.loading"
-      class="l-flex__fill l-flex--col c-timeline"
-    >
-      <div class="l-flex__none l-flex--row has-bottom-padding">
-        <div class="l-flex__auto c-sibling-item" />
-        <el-date-picker
-          v-model="current"
-          class="l-flex__none c-sibling-item u-pointer"
-          type="date"
-          placeholder="选择日期"
-          :picker-options="pickerOptions"
-          :editable="false"
-          :clearable="false"
-          @change="onTimeChange"
-        />
-        <search-input
-          v-model.trim="deviceOptions.params.name"
-          class="l-flex__none c-sibling-item"
-          placeholder="设备名称"
-          @search="search"
-        />
-        <button
-          class="l-flex__none c-sibling-item near o-button"
-          @click="search"
-        >
-          搜索
-        </button>
-      </div>
-      <div class="l-flex__none l-flex c-timeline__row header">
-        <div class="l-flex__none c-timeline__left">
-          <span class="o-priority is-priority99">高</span>
-          <span class="o-priority is-priority3">中</span>
-          <span class="o-priority is-priority1">低</span>
-        </div>
-        <div class="l-flex__auto l-flex--row c-timeline__right">
-          <i
-            class="l-flex__none c-sibling-item c-timeline__arrow el-icon-arrow-left u-pointer"
-            :class="{ display: canPrevious }"
-            @click="offsetTime(-1)"
-          />
-          <div class="l-flex__auto l-flex--row c-sibling-item c-timeline__time">
-            <div
-              v-for="time in times"
-              :key="time"
-              class="l-flex__none"
-            >
-              {{ time }}
-            </div>
-          </div>
-          <i
-            class="l-flex__none c-sibling-item c-timeline__arrow display el-icon-arrow-right u-pointer"
-            @click="offsetTime(1)"
-          />
-        </div>
-      </div>
-      <div class="l-flex__self l-flex--col c-timeline__main u-relative">
-        <div class="l-flex__auto u-overflow-y--auto">
-          <div
-            v-for="item in deviceOptions.list"
-            :key="item.id"
-            class="l-flex c-timeline__row"
-            :class="{ selected: item.id === deviceId }"
-            @click="chooseProgramProxy(item)"
-          >
-            <div class="l-flex__none c-timeline__left u-relative u-pointer">
-              <div class="u-ellipsis">{{ item.name }}</div>
-            </div>
-            <div class="l-flex__auto l-flex--col c-timeline__right">
-              <div
-                v-if="item.options.loading"
-                class="l-flex--row c-timeline__programs"
-              >
-                <i class="el-icon-loading has-padding--h" />加载中...
-              </div>
-              <div
-                v-else-if="item.options.error"
-                class="l-flex--row c-timeline__programs has-padding--h"
-              >
-                <el-link
-                  type="warning"
-                  @click.stop="getTimeline(item)"
-                >
-                  获取失败,点击重试
-                </el-link>
-              </div>
-              <template v-else-if="item.options.list.length">
-                <div
-                  v-for="(programs, index) in item.options.list"
-                  :key="index"
-                  class="c-timeline__programs l-flex--row u-relative"
-                >
-                  <div
-                    v-for="program in programs"
-                    :key="program.key"
-                    class="l-flex__none l-flex--row c-event-program u-pointer"
-                    :class="[{ 'selected': program.event.selected }, `is-priority${program.event.priority}`]"
-                    :style="program.style"
-                    @click.stop="chooseProgramProxy(item, program)"
-                  >
-                    <i
-                      class="l-flex__none c-event-program__img o-program is-ratio--16_9"
-                      :style="program.event.style"
-                    />
-                    <div class="l-flex__auto">
-                      <auto-text
-                        class="c-event-program__time"
-                        :text="program.time"
-                        :tag="program.style.width"
-                      />
-                      <auto-text
-                        class="c-event-program__name"
-                        :text="program.event.name"
-                        :tag="program.style.width"
-                      />
-                    </div>
-                  </div>
-                </div>
-              </template>
-              <div
-                v-else
-                class="l-flex--row c-timeline__programs has-padding--h"
-              >
-                当前时段暂无节目
-              </div>
-            </div>
-          </div>
-        </div>
-        <status-wrapper
-          v-if="isAbnormal"
-          :error="deviceOptions.error"
-          @click="getDevices"
-        />
-        <div
-          v-show="style"
-          class="c-timeline__line"
-        >
-          <div
-            class="c-timeline__mask"
-            :style="style"
-          />
-        </div>
-      </div>
-      <pagination
-        :total="deviceOptions.totalCount"
-        :page.sync="deviceOptions.params.pageNum"
-        :limit.sync="deviceOptions.params.pageSize"
-        @pagination="getDevices"
-      />
-    </div>
-    <material-dialog ref="materialDialog" />
-  </wrapper>
-</template>
-
-<script>
-import {
-  getDevices,
-  getTimeline
-} from '@/api/device'
-import { EventPriorityInfo } from '@/constant'
-import {
-  toDate,
-  toDateStr,
-  toTimeStr,
-  toZeroPoint,
-  getNearestHitDate,
-  getStartDate,
-  getFinishDate,
-  pickMin,
-  pickMax,
-  getEventDescription
-} from '@/utils/event'
-import { EventCache } from '@/utils/cache'
-import { createListOptions } from '@/utils'
-
-export default {
-  name: 'ScheduleTimeline',
-  data () {
-    return {
-      deviceOptions: createListOptions({
-        name: '',
-        activate: 1,
-        pageSize: 5
-      }),
-      style: null,
-      canPrevious: false,
-      startHour: 0,
-      times: [],
-      current: null,
-      device: null,
-      programProxy: null
-    }
-  },
-  computed: {
-    deviceId () {
-      return this.device?.id
-    },
-    deivceName () {
-      return this.device?.name
-    },
-    programName () {
-      return this.programProxy?.event.name
-    },
-    programTime () {
-      return this.programProxy?.event.time
-    },
-    programStyle () {
-      return this.programProxy?.event.style
-    },
-    isAbnormal () {
-      const deviceOptions = this.deviceOptions
-      return deviceOptions.error || !deviceOptions.loading && deviceOptions.totalCount === 0
-    },
-    pickerOptions () {
-      return {
-        disabledDate: this.isDisableDate
-      }
-    }
-  },
-  created () {
-    this.initTimes(new Date())
-    this.getDevices()
-    this.$timer = setInterval(this.calcLine, 1000)
-  },
-  beforeDestroy () {
-    clearInterval(this.$timer)
-  },
-  methods: {
-    getDevices () {
-      this.device = null
-      if (this.programProxy) {
-        this.programProxy.event.selected = false
-      }
-      this.programProxy = null
-      const options = this.deviceOptions
-      options.error = false
-      options.loading = true
-      getDevices(options.params).then(({ data, totalCount }) => {
-        options.list = data.map(this.transform)
-        options.totalCount = totalCount
-        options.list.forEach(this.getTimeline)
-      }, () => {
-        options.error = true
-        options.list = []
-      }).finally(() => {
-        options.loading = false
-      })
-    },
-    search () {
-      const options = this.deviceOptions
-      options.list = []
-      options.totalCount = 0
-      options.params.pageNum = 1
-      this.getDevices()
-    },
-    transform (device) {
-      const { id, name } = device
-      return {
-        id, name,
-        options: {
-          loading: true,
-          error: false,
-          events: [],
-          list: []
-        }
-      }
-    },
-    getTimeline (device) {
-      const options = device.options
-      options.error = false
-      options.loading = true
-      getTimeline(device.id, { custom: true }).finally(() => {
-        options.loading = false
-      }).then(
-        events => {
-          const now = Date.now()
-          options.events = this.transformEvents(events.filter(({ until }) => !until || now <= toDate(until).getTime()))
-          this.calcEvents(options)
-        },
-        () => {
-          options.error = true
-          options.list = []
-        }
-      )
-    },
-    transformEvent (event) {
-      return {
-        ...event,
-        name: event.target.name || EventPriorityInfo[event.priority],
-        time: getEventDescription(event),
-        startDateTime: toDate(event.start),
-        endDateTime: toDate(event.until),
-        style: null,
-        selected: false,
-        img () {
-          let promise = null
-          switch (this.target.type) {
-            case EventTarget.RECUR:
-              promise = EventCache.getImage(EventTarget.PROGRAM, this.target.programs[0]?.programId)
-              break
-            default:
-              promise = EventCache.getImage(this.target.type, this.target.id)
-              break
-          }
-          promise.then(img => {
-            if (img) {
-              this.style = {
-                backgroundSize: 'contain',
-                backgroundImage: `url("${img}")`
-              }
-            }
-          })
-        }
-      }
-    },
-    transformEvents (events) {
-      const map = {}
-      const now = Date.now()
-      for (let i = 0; i < events.length; i++) {
-        const event = this.transformEvent(events[i])
-        event.key = `${i}_${now}`
-        if (!map[event.priority]) {
-          map[event.priority] = []
-        }
-        map[event.priority].push(event)
-      }
-      return Object.keys(map)
-        .sort((a, b) => a > b ? -1 : 1)
-        .map(key => map[key].sort((a, b) => toDate(a.start) - toDate(b.start)))
-    },
-    isDisableDate (date) {
-      const now = new Date()
-      const min = new Date(now.getFullYear(), now.getMonth(), now.getDate())
-      const max = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 30)
-      return date < min || date > max
-    },
-    initTimes (date) {
-      const maxDate = pickMax(toDate(date), new Date())
-      this.current = toZeroPoint(maxDate)
-      this.startHour = Math.min(20, maxDate.getHours())
-      this.refreshTimes(this.startHour)
-    },
-    refreshTimes (start) {
-      const times = []
-      for (let i = 0; i < 5; i++) {
-        times.push(`${(start + i).toString().padStart(2, '0')}:00`)
-      }
-      this.times = times
-
-      this.$startDateTime = toDate(this.current.getTime() + start * 3600000)
-      this.$endDateTime = toDate(this.current.getTime() + (start + 4) * 3600000)
-      this.calcLine()
-
-      this.refreshTimeline()
-    },
-    calcLine () {
-      const now = Date.now()
-      this.canPrevious = now < this.$startDateTime
-      if (now < this.$startDateTime || now >= this.$endDateTime) {
-        this.style = null
-      } else {
-        this.style = {
-          left: `${Math.min(100, (now - this.$startDateTime) / 144000)}%`
-        }
-      }
-    },
-    refreshTimeline () {
-      this.deviceOptions.list.forEach(device => {
-        this.calcEvents(device.options)
-      })
-    },
-    offsetTime (offset) {
-      const next = this.startHour + offset
-      if (offset < 0) {
-        const timestamp = this.current.getTime() + next * 3600000
-        const now = new Date()
-        now.setMinutes(0)
-        now.setSeconds(0)
-        now.setMilliseconds(0)
-        if (timestamp >= now) {
-          if (next < 0) {
-            this.initTimes(timestamp)
-          } else {
-            this.refreshTimes(this.startHour = next)
-          }
-        }
-      } else if (next > 20) {
-        this.initTimes(this.$endDateTime)
-      } else {
-        this.refreshTimes(this.startHour = next)
-      }
-    },
-    onTimeChange (val) {
-      this.initTimes(val)
-    },
-    calcSamePriorityEvents (events) {
-      const total = 144000
-      const arr = []
-      for (let i = 0; i < events.length; i++) {
-        const event = events[i]
-        const { startDateTime, endDateTime } = event
-        if (endDateTime && endDateTime <= this.$startDateTime || startDateTime >= this.$endDateTime) {
-          continue
-        }
-        const hit = getNearestHitDate(event, this.$startDateTime, this.$endDateTime)
-        if (hit) {
-          const startDate = getStartDate(event, hit)
-          const endDate = getFinishDate(event, hit)
-          arr.push({
-            key: event.key,
-            event,
-            time: `${toDateStr(startDate)} ${toTimeStr(startDate)} - ${toDateStr(endDate)} ${toTimeStr(endDate)}`,
-            style: {
-              left: `${(hit - this.$startDateTime) / total}%`,
-              width: `${(pickMin(this.$endDateTime, getFinishDate(event, hit)) - hit) / total}%`,
-              zIndex: event.priority
-            }
-          })
-          event.img?.()
-          if (endDate >= this.$endDateTime) {
-            break
-          }
-        }
-      }
-      return arr
-    },
-    calcEvents (options) {
-      if (options.loading || options.error) {
-        return
-      }
-      options.list = options.events.map(this.calcSamePriorityEvents).filter(events => events.length)
-    },
-    chooseProgramProxy (device, programProxy) {
-      this.device = device
-      if (this.programProxy) {
-        this.programProxy.event.selected = false
-      }
-      if (programProxy) {
-        programProxy.event.selected = true
-      }
-      this.programProxy = programProxy
-    },
-    onView () {
-      if (this.programProxy) {
-        this.$refs.materialDialog.showEventTarget(this.programProxy.event.target)
-      }
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.c-device-detail {
-  &__screen {
-    width: 352px;
-    margin-right: 24px;
-  }
-
-  &__name {
-    color: $black;
-    font-size: 20px;
-    font-weight: bold;
-    line-height: 1;
-  }
-
-  &__program {
-    margin-top: 20px;
-    color: $blue;
-    font-size: 20px;
-    font-weight: bold;
-  }
-
-  &__time {
-    margin-top: $spacing;
-    color: $info--dark;
-    font-size: 20px;
-  }
-}
-
-.c-timeline {
-  min-height: 400px;
-
-  &__main {
-    border: 1px solid $border;
-  }
-
-  &__row {
-    & + & {
-      border-top: 1px solid $border;
-    }
-  }
-
-  &__row.header {
-    .c-timeline__left {
-      border-right: none;
-    }
-  }
-
-  &__row.header &__right {
-    color: $black;
-    user-select: none;
-    background-color: transparent;
-  }
-
-  &__row.selected &__left {
-    color: #fff;
-    background-color: #9fbfe8;
-  }
-
-  &__row.selected &__left::after {
-    content: "";
-    position: absolute;
-    top: 0;
-    left: 0;
-    bottom: 0;
-    width: 4px;
-    background-color: $blue;
-  }
-
-  &__left {
-    display: inline-flex;
-    align-items: center;
-    width: 210px;
-    padding: 0 10px 0 20px;
-    margin-right: 1px;
-    color: $black;
-    font-size: 16px;
-    background-color: #fafbfc;
-    border-right: 1px solid $border;
-  }
-
-  &__right {
-    position: relative;
-    color: $info--dark;
-    font-size: 14px;
-    line-height: 1;
-    overflow: hidden;
-  }
-
-  &__programs {
-    box-sizing: content-box;
-    height: 54px;
-    padding: 2px 0;
-
-    & + & {
-      border-top: 1px dashed $border;
-    }
-  }
-
-  &__arrow {
-    visibility: hidden;
-    padding: 6px;
-    color: #fff;
-    font-size: 12px;
-    border-radius: $radius--sm;
-    background-color: $blue;
-
-    &.display {
-      visibility: visible;
-    }
-  }
-
-  &__time {
-    justify-content: space-between;
-    padding: 10px 0;
-    color: $black;
-    font-size: 14px;
-  }
-
-  &__line {
-    position: absolute;
-    top: -12px;
-    left: 210px;
-    right: 0;
-    bottom: 0;
-    pointer-events: none;
-  }
-
-  &__mask {
-    position: absolute;
-    top: 0;
-    left: 0;
-    bottom: 0;
-    color: #ff0000;
-    border-right: 1px solid currentColor;
-    z-index: 999;
-
-    &::after {
-      content: "";
-      position: absolute;
-      top: 0;
-      right: -5px;
-      width: 9px;
-      height: 9px;
-      border-radius: 50%;
-      background-color: currentColor;
-    }
-  }
-}
-
-.c-event-program {
-  position: absolute;
-  top: 0;
-  bottom: 0;
-  padding: 0 4px;
-  font-size: 12px;
-  overflow: hidden;
-
-  &:hover {
-    color: #fff;
-    background-color: rgba($blue, 0.4);
-  }
-
-  &.selected {
-    color: #fff;
-    background-color: $blue;
-    z-index: 99;
-  }
-
-  &__img {
-    width: 96px;
-    margin-right: 8px;
-  }
-
-  &__name {
-    margin-top: 10px;
-  }
-}
-
-.o-priority {
-  display: inline-block;
-  padding: 4px;
-  font-size: $font-size--sm;
-  border-radius: $radius--sm;
-
-  & + & {
-    margin-left: 4px;
-  }
-}
-
-.o-program {
-  display: inline-block;
-  font-size: 0;
-  border-radius: $radius--sm;
-  background: rgba(#000, 0.8) url("~@/assets/program_bg.png") center center /
-    100% 100% no-repeat;
-}
-</style>

+ 4 - 8
src/views/device/timeline/index.vue

@@ -145,14 +145,13 @@ import {
 } from '@/constant'
 import {
   toDate,
-  toDateStr,
   toTimeStr,
   toZeroPoint,
   getNearestHitDate,
-  getStartDate,
   getFinishDate,
   pickMin,
   pickMax,
+  correctEndTime,
   getEventDescription
 } from '@/utils/event'
 import { EventCache } from '@/utils/cache'
@@ -307,9 +306,8 @@ export default {
           this.$endDateTime
         )
         if (hit) {
-          const startDate = getStartDate(event, hit)
           const endDate = getFinishDate(event, hit)
-          const end = pickMin(this.$endDateTime, getFinishDate(event, hit))
+          const end = pickMin(this.$endDateTime, endDate)
           const startHour = hit.getHours()
 
           let endHour = end.getHours()
@@ -337,7 +335,7 @@ export default {
           }
           intervalDisplayMap[startHour] = true
           intervalDisplayMap[endHour] = true
-          //
+
           arr.push({
             startHour,
             endHour,
@@ -345,9 +343,7 @@ export default {
             end,
             key: event.key,
             event,
-            time: `${toDateStr(startDate)} ${toTimeStr(
-              startDate
-            )} - ${toDateStr(endDate)} ${toTimeStr(endDate)}`
+            time: `${toTimeStr(hit)} - ${correctEndTime(toTimeStr(end))}`
           })
           event.img?.()
           if (endDate >= this.$endDateTime) {

+ 8 - 12
src/views/screen/deploy/ratio/components/RatioTree.vue

@@ -13,7 +13,7 @@
         v-if="isEmpty"
         class="c-ratio-tree__empty u-font-size u-bold u-text--center"
       >
-        暂无设备
+        暂无数据
       </div>
       <div
         v-else
@@ -51,17 +51,12 @@ export default {
       return this.productTypes.length === 0
     }
   },
-  watch: {
-    active: {
-      handler () {
-        this.getProductTypes()
-      },
-      immediate: true
-    }
+  created () {
+    this.getProductTypes()
   },
   methods: {
     onToggle (productType) {
-      if (!this.selectedItem || this.selectedItem.id !== productType.id) {
+      if (!this.selectedItem || productType && this.selectedItem.id !== productType.id) {
         if (this.selectedItem) {
           this.selectedItem.selected = false
         }
@@ -76,17 +71,16 @@ export default {
       getProductTypes({
         pageSize: 10,
         pageNum: 1
-      }).then(({ data, totalCount }) => {
+      }, { custom: true }).then(({ data, totalCount }) => {
         if (totalCount <= 10) {
           return { data }
         }
         return getProductTypes({
           pageSize: totalCount,
           pageNum: 1
-        })
+        }, { custom: true })
       }).then(
         ({ data }) => {
-          this.loading = false
           this.productTypes = data.map(({ id, name }) => {
             return {
               id,
@@ -94,6 +88,8 @@ export default {
               selected: false
             }
           })
+          this.onToggle(this.productTypes[0])
+          this.loading = false
         },
         () => {
           this.error = true

+ 3 - 1
src/views/screen/deploy/ratio/index.vue

@@ -98,11 +98,13 @@ import {
 } from '@/utils/event'
 import { publish } from '@/api/platform'
 import EventFrequencyConfigDialog from '../components/EventFrequencyConfigDialog.vue'
+import RatioTree from './components/RatioTree.vue'
 
 export default {
   name: 'DeployRatio',
   components: {
-    EventFrequencyConfigDialog
+    EventFrequencyConfigDialog,
+    RatioTree
   },
   data () {
     return {