|
|
<template>
|
|
|
<div class="board-item-container" ref="board-item-container">
|
|
|
<div
|
|
|
class="board-item-container-item"
|
|
|
v-for="(item,index) in rows"
|
|
|
:key="`${item.id}-${item.scroll}`"
|
|
|
:style="`
|
|
|
height: ${heights[index]}px;
|
|
|
line-height: ${heights[index]}px;
|
|
|
transition: all .2s;
|
|
|
`"
|
|
|
@click="showDetail(item,true)">
|
|
|
<dv-border-box-13 style="width: 100%;height: 100%;min-height: .5px;" :style="{ 'opacity': heights[index] ? 1 : 0}">
|
|
|
<div style="width: 100%;height: 100%;padding: 30px 20px;line-height: 1;" class="d-flex flex-column jc-between flex-1">
|
|
|
<div class="board-item__top d-flex jc-between ai-center">
|
|
|
<dv-decoration-11 style="width: 160px;height: 48px;" :style="{ 'color': item.level === 2 ? 'red' : '#fff' }">{{ item.equipment_id_equipments_id_relation ? item.equipment_id_equipments_id_relation.name : '' }}</dv-decoration-11>
|
|
|
<template v-if="item.level === 2">
|
|
|
<Icon type="ios-alert" color="red" style="font-size: 26px;flex: 1;" class="d-flex ai-left"/>
|
|
|
</template>
|
|
|
<template v-if="[2,3,4,5].find(i => i === item.status)">
|
|
|
<dv-percent-pond :config="{
|
|
|
value: (item.status === 2 || item.status === 4) ? 0 : 50,
|
|
|
colors: ['#01c4f9', '#c135ff'],
|
|
|
lineDash: [6,3]
|
|
|
}"
|
|
|
style="width:140px;height:36px;zoom: 0.9;" />
|
|
|
</template>
|
|
|
</div>
|
|
|
<div class="board-item__bottom d-flex jc-between ai-start">
|
|
|
<div class="time-info">
|
|
|
<div v-for="(label,key) in contentLK" style="display: inline-block;">
|
|
|
{{label}}:{{ $moment(item[key]).format('YYYY-MM-DD HH:mm') || '-' }}
|
|
|
</div>
|
|
|
<div v-if="item.status === 3 || item.status === 2" :style="{ 'color': lastTimeColor($moment(new Date(item.start_time)).diff($moment(time),'minutes')) }">
|
|
|
倒计时:{{ $moment(new Date(item.start_time)).diff($moment(time),'minutes') }}分
|
|
|
</div>
|
|
|
</div>
|
|
|
<div v-if="item.status && item.status !== 6 && item.status !== 7" @click.stop="showDetail(item)">
|
|
|
<dv-border-box-8 reverse class="fw-b text-center" style="width: 72px;height: 40px;line-height: 40px;cursor: pointer;"
|
|
|
>{{setStatusText(item.status)}}</dv-border-box-8>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</dv-border-box-13>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { deepCopy } from "@/utils";
|
|
|
import { save } from "@/api/system/baseForm";
|
|
|
|
|
|
export default {
|
|
|
inject: ['showModal'],
|
|
|
props: {
|
|
|
transfers: Array,
|
|
|
setTransferStatusNumber: Number,
|
|
|
contentLK: Object,
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
nowRow: {},
|
|
|
dom: '',
|
|
|
needCalc: false,
|
|
|
rowNum: 4,
|
|
|
height: 0,
|
|
|
width: 0,
|
|
|
avgHeight: 0,
|
|
|
updater: 0,
|
|
|
animationIndex: 0,
|
|
|
heights: [],
|
|
|
animationHandler: '',
|
|
|
copyTransfers: [],
|
|
|
rows: [],
|
|
|
typeMap: new Map([
|
|
|
[1,'待下发'],
|
|
|
[2,'已下发'],
|
|
|
[3,'待执行'],
|
|
|
[4,'执行中'],
|
|
|
[5,'已取消'],
|
|
|
[6,'已完成']
|
|
|
]),
|
|
|
time: new Date(),
|
|
|
timer: null
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
showDetail (item,isShow=false) {
|
|
|
if (isShow) {
|
|
|
this.nowRow = deepCopy(item);
|
|
|
this.$emit('showDetail', { item,isShow })
|
|
|
return
|
|
|
}
|
|
|
if (item.status === 2 || item.status === 4) {
|
|
|
this.$confirm("确认要通知现场?","提示",{
|
|
|
confirmButtonText: '确定',
|
|
|
cancelButtonText: '取消',
|
|
|
type: 'warning',
|
|
|
customClass: "big-screen-modal"
|
|
|
}).then(res => {
|
|
|
let copyData = deepCopy(item);
|
|
|
copyData.status = item.status === 2 ? 3 : 5;
|
|
|
for (let key in copyData) {
|
|
|
if (/_relation/g.test(key)) {
|
|
|
delete copyData[key]
|
|
|
}
|
|
|
}
|
|
|
save({
|
|
|
table_name: 'transfers',
|
|
|
...copyData
|
|
|
}).then(_ => {
|
|
|
this.$emit('refresh')
|
|
|
})
|
|
|
})
|
|
|
} else {
|
|
|
this.nowRow = deepCopy(item);
|
|
|
this.$emit('showDetail',{ item, isShow })
|
|
|
}
|
|
|
},
|
|
|
|
|
|
setTransferStatus (data) {
|
|
|
const { status, start_sign, end_sign } = data;
|
|
|
|
|
|
let copyRow = deepCopy(this.nowRow);
|
|
|
if (status === 4) {
|
|
|
copyRow.act_start_time = this.$moment().format('YYYY-MM-DD HH:mm')
|
|
|
copyRow.start_sign = start_sign
|
|
|
}
|
|
|
if (status === 6) {
|
|
|
copyRow.act_end_time = this.$moment().format('YYYY-MM-DD HH:mm')
|
|
|
copyRow.end_sign = end_sign
|
|
|
}
|
|
|
copyRow.status = status;
|
|
|
for (let key in copyRow) {
|
|
|
if (/_relation/g.test(key)) {
|
|
|
delete copyRow[key]
|
|
|
}
|
|
|
}
|
|
|
save({
|
|
|
table_name: 'transfers',
|
|
|
...copyRow
|
|
|
}).then(_ => {
|
|
|
this.$emit('refresh')
|
|
|
})
|
|
|
},
|
|
|
|
|
|
|
|
|
initWH (resize = true) {
|
|
|
const { $nextTick, $refs, onResize } = this
|
|
|
|
|
|
return new Promise(resolve => {
|
|
|
$nextTick(_ => {
|
|
|
const dom = this.dom = $refs['board-item-container']
|
|
|
|
|
|
this.width = dom ? dom.clientWidth : 0
|
|
|
this.height = dom ? dom.clientHeight : 0
|
|
|
|
|
|
if (!dom) {
|
|
|
console.warn('DataV: Failed to get dom node, component rendering may be abnormal!')
|
|
|
} else if (!this.width || !this.height) {
|
|
|
console.warn('DataV: Component width or height is 0px, rendering abnormality may occur!')
|
|
|
}
|
|
|
|
|
|
if (typeof onResize === 'function' && resize) onResize()
|
|
|
|
|
|
resolve()
|
|
|
})
|
|
|
})
|
|
|
},
|
|
|
calcHeights (onresize = false) {
|
|
|
const { height, rowNum } = this
|
|
|
|
|
|
let allHeight = this.height
|
|
|
|
|
|
const avgHeight = allHeight / rowNum
|
|
|
|
|
|
this.avgHeight = avgHeight
|
|
|
|
|
|
if (!onresize) this.heights = new Array(this.transfers.length).fill(avgHeight)
|
|
|
|
|
|
},
|
|
|
async animation (start = false) {
|
|
|
const { needCalc, calcHeights } = this
|
|
|
|
|
|
if (needCalc) {
|
|
|
calcHeights()
|
|
|
this.needCalc = false;
|
|
|
}
|
|
|
|
|
|
let { avgHeight, animationIndex, mergedConfig, animation, updater } = this
|
|
|
|
|
|
const { waitTime, carousel, rowNum } = {
|
|
|
waitTime: 8000,
|
|
|
carousel: 'single',
|
|
|
rowNum: this.rowNum
|
|
|
}
|
|
|
|
|
|
const rowLength = this.copyTransfers.length
|
|
|
|
|
|
if (rowNum >= rowLength) return
|
|
|
|
|
|
if (start) {
|
|
|
await new Promise(resolve => setTimeout(resolve, waitTime))
|
|
|
if (updater !== this.updater) return
|
|
|
}
|
|
|
|
|
|
|
|
|
const animationNum = carousel === 'single' ? 1 : rowNum
|
|
|
let rows = this.copyTransfers.slice(animationIndex)
|
|
|
rows.push(...this.copyTransfers.slice(0, animationIndex))
|
|
|
|
|
|
this.rows = rows.slice(0, carousel === 'page' ? rowNum * 2 : rowNum + 1)
|
|
|
this.heights = new Array(rowLength).fill(this.avgHeight)
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300))
|
|
|
if (updater !== this.updater) return
|
|
|
|
|
|
this.heights.splice(0, animationNum, ...new Array(animationNum).fill(0))
|
|
|
|
|
|
animationIndex += animationNum
|
|
|
|
|
|
const back = animationIndex - rowLength
|
|
|
if (back >= 0) animationIndex = back
|
|
|
|
|
|
this.animationIndex = animationIndex
|
|
|
this.animationHandler = setTimeout(animation, waitTime - 300)
|
|
|
},
|
|
|
stopAnimation () {
|
|
|
const { animationHandler, updater } = this
|
|
|
|
|
|
this.updater = (updater + 1) % 999999
|
|
|
|
|
|
if (!animationHandler) return
|
|
|
|
|
|
clearTimeout(animationHandler)
|
|
|
},
|
|
|
},
|
|
|
computed: {
|
|
|
setStatusText () {
|
|
|
return function (status) {
|
|
|
const textMap = new Map([
|
|
|
[2,'通知现场'],
|
|
|
[3,'确认开启'],
|
|
|
[4,'通知现场'],
|
|
|
[5,'确认关闭']
|
|
|
])
|
|
|
return textMap.get(status)
|
|
|
}
|
|
|
},
|
|
|
lastTimeColor () {
|
|
|
return function (min) {
|
|
|
if (min <= 0) {
|
|
|
return "red"
|
|
|
} else if (min > 0 && min <= 5) {
|
|
|
return "orange"
|
|
|
} else {
|
|
|
return "#eee"
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
watch: {
|
|
|
async transfers(val) {
|
|
|
const h = this.$createElement;
|
|
|
if (val && val.length > 0) {
|
|
|
this.rows = val.map((i,index) => ({...i,scroll: index}))
|
|
|
this.copyTransfers = deepCopy(val);
|
|
|
await this.$nextTick();
|
|
|
await this.initWH(false);
|
|
|
this.calcHeights();
|
|
|
await this.animation(true);
|
|
|
|
|
|
this.timer = setInterval(() => {
|
|
|
this.time = new Date()
|
|
|
|
|
|
this.rows.forEach(item => {
|
|
|
if (item.status === 2) {
|
|
|
let lastMins = this.$moment(new Date(item.start_time)).diff(this.$moment(),'minutes')
|
|
|
if (lastMins === 3) {
|
|
|
this.showModal(true,h('div',[
|
|
|
h('p',item.equipment_id_equipments_id_relation?.name),
|
|
|
h('p',item.content),
|
|
|
h('p',`开始时间:${this.$moment(item.start_time).format('YYYY-MM-DD HH:mm')}`)
|
|
|
]))
|
|
|
}
|
|
|
}
|
|
|
if (item.status === 4) {
|
|
|
let lastMins = this.$moment(new Date(item.end_time)).diff(this.$moment(),'minutes')
|
|
|
if (lastMins === 3) {
|
|
|
this.showModal(true,h('div',[
|
|
|
h('p',item.equipment_id_equipments_id_relation?.name),
|
|
|
h('p',item.content),
|
|
|
h('p',`结束时间:${this.$moment(item.end_time).format('YYYY-MM-DD HH:mm')}`)
|
|
|
]))
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
},1000 * 60)
|
|
|
} else {
|
|
|
this.rows = []
|
|
|
this.copyTransfers = []
|
|
|
await this.$nextTick();
|
|
|
await this.initWH(false);
|
|
|
this.calcHeights();
|
|
|
await this.animation(true);
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
async mounted() {
|
|
|
},
|
|
|
destroyed () {
|
|
|
clearInterval(this.timer)
|
|
|
this.$bus.$off('transferSave')
|
|
|
const { stopAnimation } = this
|
|
|
|
|
|
stopAnimation();
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.board-item {
|
|
|
width: 31%;
|
|
|
height: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
|
|
|
.equipment-name {
|
|
|
font-size: 18px;
|
|
|
letter-spacing: 1px;
|
|
|
}
|
|
|
&__title {
|
|
|
width: 40%;
|
|
|
height: 44px;
|
|
|
text-align: center;
|
|
|
font-size: 17px;
|
|
|
line-height: 44px;
|
|
|
flex: 0;
|
|
|
|
|
|
margin: auto;
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
&-container {
|
|
|
overflow: hidden;
|
|
|
flex: 1;
|
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
&-item {
|
|
|
width: 100%;
|
|
|
}
|
|
|
}
|
|
|
.time-info {
|
|
|
line-height: 1.5;
|
|
|
width: 86%;
|
|
|
display: grid;
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
grid-column-gap: 10px;
|
|
|
grid-row-gap: 5px;
|
|
|
}
|
|
|
}
|
|
|
::v-deep .row-item .ceil {
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
::v-deep .box-content {
|
|
|
height: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
justify-content: space-between;
|
|
|
line-height: 1;
|
|
|
|
|
|
padding: 30px 12px;
|
|
|
|
|
|
&-top {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 10px 10px 0 10px;
|
|
|
|
|
|
& > div:nth-child(1) {
|
|
|
background: #eccb77;
|
|
|
border-radius: 30px;
|
|
|
color: #333;
|
|
|
padding: 6px 10px;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
& > div:nth-child(2) {
|
|
|
font-weight: 600;
|
|
|
font-size: 17px;
|
|
|
}
|
|
|
}
|
|
|
&-bottom {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: flex-start;
|
|
|
|
|
|
padding: 10px 10px 0 10px;
|
|
|
|
|
|
span {
|
|
|
color: $primaryColor;
|
|
|
}
|
|
|
& > div:nth-child(1) {
|
|
|
text-align: left;
|
|
|
line-height: 2;
|
|
|
font-size: 16px;
|
|
|
font-weight: 600;
|
|
|
}
|
|
|
& > div:nth-child(2) {
|
|
|
cursor: pointer;
|
|
|
line-height: 2;
|
|
|
font-size: 15px;
|
|
|
font-weight: 600;
|
|
|
background: $primaryColor;
|
|
|
border-radius: 8px;
|
|
|
border: 2px solid rgb(119, 232, 250);
|
|
|
|
|
|
padding: 0 8px;
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
</style>
|