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.

426 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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>