|
|
@@ -0,0 +1,683 @@
|
|
|
+<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"
|
|
|
+ :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;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: "";
|
|
|
+ display: inline-block;
|
|
|
+ padding-top: $padding--16_9;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|