You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
589 lines
16 KiB
589 lines
16 KiB
<template>
|
|
<div class="container" @mouseenter="isMouseEnter = true" @mouseleave="isMouseEnter = false">
|
|
<div class="header">
|
|
<p>待运行</p>
|
|
|
|
<div class="type">
|
|
<div class="type-item" v-for="(item, index) in statusType" @click="sortTransfer(index)">
|
|
<div class="type-item__color" :style="{ 'background': item.color }"></div>
|
|
<p class="type-item__label">{{ item.label }}</p>
|
|
</div>
|
|
|
|
<div class="type-item">
|
|
<div class="type-item__operate type-item__operate-done"></div>
|
|
<div class="type-item__label">已完成</div>
|
|
</div>
|
|
<div class="type-item">
|
|
<div class="type-item__operate type-item__operate-doing"></div>
|
|
<div class="type-item__label">未执行</div>
|
|
</div>
|
|
<div class="type-item">
|
|
<div class="type-item__operate" style="background: #dcdcdc;"></div>
|
|
<div class="type-item__label">未开始</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<el-scrollbar ref="elScrollbar" class="scrollbar-wrapper">
|
|
<div class="list">
|
|
<transition-group name="list-item" ref="listItems">
|
|
<div v-for="(item, index) in scrollList" :key="item.id" ref="listItem" class="list-item" :class="`list-item-${timeStatusFormat(item)}`">
|
|
<div class="list-item__status">
|
|
<template v-if="timeStatusFormat(item) === 2">
|
|
<div class="list-item__status-2"></div>
|
|
<p>【存在运行中指令】</p>
|
|
</template>
|
|
<template v-else-if="timeStatusFormat(item) === 3">
|
|
<div class="list-item__status-3"></div>
|
|
<p>【倒计时{{ $moment(item.start_time).diff($moment(time),'minutes') }}分钟】</p>
|
|
</template>
|
|
<template v-else-if="timeStatusFormat(item) === 4">
|
|
<div class="list-item__status-4"></div>
|
|
<p>【超时】</p>
|
|
</template>
|
|
<template v-else>
|
|
|
|
</template>
|
|
</div>
|
|
<div class="list-item__name">
|
|
{{ item.equipment_id_equipments_id_relation ? item.equipment_id_equipments_id_relation.name : '' }}
|
|
</div>
|
|
<div class="list-item__content">
|
|
<el-tooltip class="item" effect="dark" :content="item.content" placement="top-start">
|
|
<span>{{ item.content }}</span>
|
|
</el-tooltip>
|
|
</div>
|
|
<div class="list-item__time">
|
|
运行时间:{{ timeFormat(item.start_time) }}至{{ timeFormat(item.end_time,'HH:mm') }}
|
|
<br>
|
|
发布时间:{{ timeFormat(item.created_at,'YYYY-MM-DD HH:mm') }}
|
|
</div>
|
|
<div class="list-item__last">预计时长 {{ $moment(item.end_time).diff($moment(item.start_time),'hours', true).toFixed(2) }}小时</div>
|
|
<div class="list-item__operate">
|
|
<div v-for="(s, si) in (item.tiaozhengleixing === 0 ? closeStatus : status)" :title="operateTitle(item, s)" class="step" @click="stepClick(item,s)">
|
|
<div class="step-icon">
|
|
<div class="step-icon__cir" :class="`step-icon__cir-${stepFormat(item.status,s.value)}`"></div>
|
|
<div class="step-icon__line" :class="`step-icon__line-${stepFormat(item.status,s.value)}`" v-if="si < (item.tiaozhengleixing === 0 ? closeStatus : status).length-1"></div>
|
|
</div>
|
|
<div class="step-label">{{ s.label }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="list-item__btn">
|
|
<Button type="primary" size="small" class="list-item__btn-show" @click="stepClick(item,{},true)">查看</Button>
|
|
<Button type="primary" size="small" class="list-item__btn-feedback" @click="$emit('callback',item)">反馈</Button>
|
|
<Icon v-if="isShowNotice(item)" type="md-alert" color="#db4f2b" class="list-item__btn-callback" @click="$emit('callbackList',item)"/>
|
|
</div>
|
|
</div>
|
|
</transition-group>
|
|
</div>
|
|
</el-scrollbar>
|
|
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { deepCopy } from "@/utils";
|
|
|
|
export default {
|
|
inject: ["transfers", "nowTime", "auths"],
|
|
data() {
|
|
return {
|
|
closeStatus: [
|
|
{
|
|
value: 2,
|
|
label: "接收",
|
|
auth: "receive"
|
|
},
|
|
{
|
|
value: 5,
|
|
label: "确认关闭通知",
|
|
auth: "noticeClose"
|
|
},
|
|
{
|
|
value: 6,
|
|
label: "确认关闭",
|
|
auth: "close"
|
|
},
|
|
],
|
|
status: [
|
|
{
|
|
value: 2,
|
|
label: "接收",
|
|
auth: "receive"
|
|
},
|
|
{
|
|
value: 3,
|
|
label: "通知开机",
|
|
auth: "noticeOpen"
|
|
},
|
|
{
|
|
value: 4,
|
|
label: "开机",
|
|
auth: "open"
|
|
},
|
|
],
|
|
statusType: [
|
|
{
|
|
label: "存在运行中",
|
|
color: "linear-gradient(to top left,#527ded, #527ded43)",
|
|
},
|
|
{
|
|
label: "超时",
|
|
color: "linear-gradient(to top left,#d15d52, #d15d5243)"
|
|
},
|
|
{
|
|
label: "即将运行",
|
|
color: "linear-gradient(to top left,#ecc069, #ecc06943)"
|
|
}
|
|
],
|
|
|
|
|
|
scrollTimer: null,
|
|
scrollList: [],
|
|
isMouseEnter: false,
|
|
isPaused: false,
|
|
}
|
|
},
|
|
methods: {
|
|
stepClick (item,s,isDetail=false) {
|
|
if (isDetail) {
|
|
this.$emit('step-click', {
|
|
data: item,
|
|
isDetail
|
|
})
|
|
return
|
|
}
|
|
if (!this.auths().find(i => i === s.auth)) {
|
|
this.$message({
|
|
type: "warning",
|
|
message: "无权限进行该操作"
|
|
})
|
|
return
|
|
}
|
|
const status = this.stepFormat(item.status,s.value)
|
|
|
|
if (status === 'doing') {
|
|
this.$emit('step-click', {
|
|
data: item,
|
|
isDetail
|
|
})
|
|
}
|
|
},
|
|
|
|
sortTransfer (index) {
|
|
const formatter = this.timeStatusFormat.bind(this)
|
|
if (index === 0) {
|
|
let filterArr = this.scrollList.filter(i => (formatter(i) === 2))
|
|
this.scrollList = Array.from(new Set([...filterArr,...this.scrollList].map(i => JSON.stringify(i)))).map(i => JSON.parse(i))
|
|
} else if (index === 1) {
|
|
let filterArr = this.scrollList.filter(i => (formatter(i) === 4))
|
|
this.scrollList = Array.from(new Set([...filterArr,...this.scrollList].map(i => JSON.stringify(i)))).map(i => JSON.parse(i))
|
|
} else if (index === 2) {
|
|
let filterArr = this.scrollList.filter(i => (formatter(i) === 3))
|
|
this.scrollList = Array.from(new Set([...filterArr,...this.scrollList].map(i => JSON.stringify(i)))).map(i => JSON.parse(i))
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
time () {
|
|
return this.nowTime()
|
|
},
|
|
toDo () {
|
|
return this.transfers("toDo")
|
|
},
|
|
|
|
timeFormat () {
|
|
return function (time,format='YYYY-MM-DD HH:mm') {
|
|
return this.$moment(time).format(format)
|
|
}
|
|
},
|
|
|
|
isShowNotice () {
|
|
return function (item) {
|
|
return item.id_feedbacks_transfer_id_relation.reduce((pre, cur) => (!!(pre || cur.status)), false)
|
|
}
|
|
},
|
|
|
|
timeStatusFormat () {
|
|
return function (item) {
|
|
//1 普通 2 存在进行中 3 倒计时 4 超时
|
|
const diffMins = this.$moment(item.start_time).diff(this.time,"minutes");
|
|
if (diffMins <= 5 && diffMins >= 0) {
|
|
if (!item._isPlay && !item._isFirst) {
|
|
item._isPlay = true
|
|
this.$audioPlay()
|
|
}
|
|
return 3
|
|
}
|
|
if (this.toDo.filter(i => (i.id === item.id))?.length > 1) {
|
|
return 2
|
|
}
|
|
if (diffMins < 0) {
|
|
if (!item._isPlay && !item._isFirst) {
|
|
item._isPlay = true
|
|
this.$audioPlay()
|
|
}
|
|
return 4
|
|
}
|
|
item._isFirst = false
|
|
return 1
|
|
}
|
|
},
|
|
|
|
stepFormat () {
|
|
return function (statue,s) {
|
|
const doneStatus = Array.from({ length: statue },((_,i) => (i + 1)))
|
|
if (statue === s) {
|
|
return "doing"
|
|
}
|
|
if (doneStatus.find(i => i === s)) {
|
|
return "done"
|
|
}
|
|
return false
|
|
}
|
|
},
|
|
|
|
operateTitle () {
|
|
return function (item, s) {
|
|
switch (s.auth) {
|
|
case 'receive':
|
|
return item.receive_time
|
|
case 'noticeOpen':
|
|
return item.notice_open_time
|
|
case 'open':
|
|
return item.open_time
|
|
default:
|
|
return ''
|
|
}
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
},
|
|
mounted() {
|
|
},
|
|
destroyed() {
|
|
clearInterval(this.scrollTimer)
|
|
},
|
|
watch: {
|
|
toDo (newVal) {
|
|
if (newVal && newVal instanceof Array) {
|
|
this.scrollList = deepCopy(newVal).map(i => {
|
|
i._isPlay = false
|
|
i._isFirst = true
|
|
return i
|
|
})
|
|
|
|
this.$nextTick(() => {
|
|
const isScroll = this.$refs['listItems']?.$el?.getBoundingClientRect()?.height > this.$refs['elScrollbar']?.$el?.getBoundingClientRect()?.height;
|
|
|
|
if (isScroll) {
|
|
if (this.scrollTimer) {
|
|
clearInterval(this.scrollTimer)
|
|
}
|
|
this.scrollTimer = setInterval(() => {
|
|
if (!this.isPaused && !this.isMouseEnter) {
|
|
this.$refs['elScrollbar'].wrap.scrollTop = 0
|
|
this.scrollList.push(this.scrollList.shift())
|
|
}
|
|
},10000)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
$container-height: calc((100vh - 8.46rem - 1.6rem * 3) / 2);
|
|
$list-height: calc(#{$container-height} - 5.33rem);
|
|
.container {
|
|
background: #FFFFFF;
|
|
box-shadow: 5px 0px 20px 0px #234382;
|
|
border-radius: 0.67rem;
|
|
|
|
position: relative;
|
|
margin: 1.6rem 3.62rem 0 3.62rem;
|
|
}
|
|
.list-item {
|
|
transition: all .4s;
|
|
}
|
|
.list-item-enter-from {
|
|
opacity: 0;
|
|
}
|
|
.header {
|
|
font-size: 1.15rem;
|
|
height: 5.33rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
background: #F5F5F5;
|
|
border-radius: .67rem .67rem 0 0 ;
|
|
|
|
padding: 0 2rem;
|
|
|
|
p {
|
|
font-weight: 600;
|
|
}
|
|
.type {
|
|
display: flex;
|
|
|
|
&-item {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
|
|
margin-left: 2rem;
|
|
&__color {
|
|
width: 1.6rem;
|
|
height: 1.6rem;
|
|
border-radius: 3px;
|
|
|
|
margin-right: .6rem;
|
|
}
|
|
&__label {
|
|
font-weight: normal;
|
|
}
|
|
$done-color: #ec6a5e;
|
|
$doing-color: #7ccac8;
|
|
&__operate {
|
|
width: 1.6rem;
|
|
height: 1.6rem;
|
|
background: #dcdcdc;
|
|
border-radius: 100%;
|
|
|
|
margin-right: .6rem;
|
|
z-index: 2;
|
|
position: relative;
|
|
&-doing {
|
|
cursor: pointer;
|
|
transform: scale(.9, .9);
|
|
background: $doing-color;
|
|
|
|
position: relative;
|
|
|
|
&::before {
|
|
content: "";
|
|
width: 132%;
|
|
height: 132%;
|
|
border-radius: 100%;
|
|
opacity: 0.4;
|
|
background: $doing-color;
|
|
transform: translate(-50%,-50%);
|
|
animation: scale infinite ease-out 4s;
|
|
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
}
|
|
@keyframes scale {
|
|
0%,100% {
|
|
transform: translate(-50%,-50%);
|
|
}
|
|
50% {
|
|
transform: translate(-50%,-50%) scale(1.1,1.1);
|
|
}
|
|
}
|
|
}
|
|
&-done {
|
|
background: $done-color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.list {
|
|
height: $list-height;
|
|
|
|
&-item {
|
|
font-size: 1.15rem;
|
|
display: flex;
|
|
align-items: center;
|
|
border-bottom: 1px #fff solid;
|
|
|
|
padding: 1.2rem 2rem;
|
|
|
|
&:nth-last-child(1) {
|
|
border-radius: 0 0 .67rem .67rem;
|
|
border-bottom: none;
|
|
}
|
|
|
|
$bkg-colors: #fff,linear-gradient(to bottom,#527ded18, #527ded28),linear-gradient(to bottom,#ecc06918, #ecc06928),linear-gradient(to bottom,#d15d5218, #d15d5228);
|
|
@for $i from 1 through length($bkg-colors) {
|
|
&-#{$i} {
|
|
background: nth($bkg-colors,$i);
|
|
|
|
@if $i == 3 {
|
|
border: 1px solid #d15d52aa;
|
|
border-bottom: 1px solid #d15d52aa !important;
|
|
|
|
& + & {
|
|
border-top: none;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&__status {
|
|
display: flex;
|
|
align-items: center;
|
|
font-weight: 600;
|
|
flex-basis: 12%;
|
|
|
|
$font-colors: #333, #527ded, #ecc069,#d15d52;
|
|
$colors: #fff,linear-gradient(to top left,#527ded, #527ded43),linear-gradient(to top left,#ecc069, #ecc06943),linear-gradient(to top left,#d15d52, #d15d5243);
|
|
@for $i from 1 through length($colors) {
|
|
&-#{$i} {
|
|
background: nth($colors,$i);
|
|
width: 1.28rem;
|
|
height: 1.28rem;
|
|
border-radius: 3px;
|
|
& + p {
|
|
color: nth($font-colors,$i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
&__name {
|
|
font-weight: 600;
|
|
font-size: 1.34rem;
|
|
flex: 1;
|
|
}
|
|
&__content {
|
|
flex-basis: 14%;
|
|
word-break: keep-all;
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
}
|
|
&__time {
|
|
flex-basis: 19%;
|
|
text-align: left;
|
|
}
|
|
&__last {
|
|
flex-basis: 9%;
|
|
text-align: center;
|
|
}
|
|
&__operate {
|
|
flex-basis: 22%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.step {
|
|
width: 6.6rem;
|
|
|
|
&-icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
position: relative;
|
|
|
|
$done-color: #ec6a5e;
|
|
$doing-color: #7ccac8;
|
|
&__cir {
|
|
width: 2.2rem;
|
|
height: 2.2rem;
|
|
background: #dcdcdc;
|
|
border-radius: 100%;
|
|
|
|
z-index: 2;
|
|
position: relative;
|
|
&-doing {
|
|
cursor: pointer;
|
|
transform: scale(.9, .9);
|
|
background: $doing-color;
|
|
|
|
position: relative;
|
|
|
|
&::before {
|
|
content: "";
|
|
width: 132%;
|
|
height: 132%;
|
|
border-radius: 100%;
|
|
opacity: 0.4;
|
|
background: $doing-color;
|
|
transform: translate(-50%,-50%);
|
|
animation: scale infinite ease-out 4s;
|
|
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
}
|
|
@keyframes scale {
|
|
0%,100% {
|
|
transform: translate(-50%,-50%);
|
|
}
|
|
50% {
|
|
transform: translate(-50%,-50%) scale(1.1,1.1);
|
|
}
|
|
}
|
|
}
|
|
&-done {
|
|
background: $done-color;
|
|
}
|
|
}
|
|
&__line {
|
|
width: 100%;
|
|
height: 2px;
|
|
background: #dcdcdc;
|
|
|
|
position: absolute;
|
|
left: 50%;
|
|
|
|
&-done {
|
|
background: $done-color;
|
|
}
|
|
}
|
|
|
|
}
|
|
&-label {
|
|
text-align: center;
|
|
font-size: 1.05rem;
|
|
line-height: 1.5;
|
|
|
|
margin-top: 4px;
|
|
}
|
|
}
|
|
}
|
|
&__btn {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-basis: 12%;
|
|
|
|
&-show, &-feedback {
|
|
font-size: 1.3rem;
|
|
height: 2.4rem;
|
|
width: 5rem;
|
|
background: #a4ddf0;
|
|
color: #333;
|
|
border-color: #a4ddf0;
|
|
}
|
|
&-callback {
|
|
font-size: 2.2rem;
|
|
margin-left: 6px;
|
|
animation: flash 5s infinite linear;
|
|
cursor: pointer;
|
|
|
|
@keyframes flash {
|
|
0%,4%,100% {
|
|
opacity: 1;
|
|
}
|
|
2% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
<style lang="scss">
|
|
#app:has(#big-screen) {
|
|
.scrollbar-wrapper {
|
|
border-radius: 0 0 0.67rem 0.67rem;
|
|
}
|
|
}
|
|
</style>
|