TaskDetailPanel.vue 4.75 KB
<template>
	<div class="right-top-box">
		<div ref="elStepContainer" class="elStep" @mouseenter="onElStepMouseEnter" @mouseleave="onElStepMouseLeave" @touchstart="onElStepTouchStart" @touchmove="onElStepTouchMove" @touchend="onElStepTouchEnd" @touchcancel="onElStepTouchEnd">
			<el-steps finish-status="success" :active="activeStep + 1" space="auto" class="custom-steps">
				<el-step v-for="(item, index) in deviceStatus" :key="index">
					<template #title>
						<div class="step-title-wrapper">
							<span v-if="item.value != null" class="step-title-clickable">
								{{ item.key }}
							</span>
							<span v-else>
								{{ item.key }}
							</span>
							<span class="step-time">{{ item.time }}</span>
						</div>
						<div class="step-value">{{ item.value }}</div>
						<div>
							<div class="solt-Moees">
								{{ item.Message }}
							</div>
						</div>
						<div class="solt-text">
							{{ item.handlePlan }}
						</div>
					</template>
				</el-step>
			</el-steps>
		</div>
		<div class="field-display-area">
			<div class="field-item" v-for="(field, index) in fieldList" :key="index">
				<div class="field-label">{{ field.label }}</div>
				<div class="field-value">{{ field.value }}</div>
			</div>
		</div>
	</div>
</template>

<script>
export default {
	name: 'TaskDetailPanel',
	props: {
		// 当前步骤下标,用于控制 ElementUI 步骤条高亮位置。
		activeStep: {
			type: Number,
			default: 0,
		},
		// 任务阶段列表,展示任务流转步骤和异常信息。
		deviceStatus: {
			type: Array,
			default: () => [],
		},
		// 任务基础字段列表,展示红框详情区的字段和值。
		fieldList: {
			type: Array,
			default: () => [],
		},
	},
	data() {
		return {
			isElStepHovered: false,
			isElStepTouching: false,
			elStepTouchEndTimer: null,
			elStepMouseLeaveTimer: null,
			elStepWheelHandler: null,
		}
	},
	watch: {
		activeStep() {
			this.scheduleCenterCurrentStep()
		},
		deviceStatus() {
			this.scheduleCenterCurrentStep()
		},
	},
	methods: {
		scheduleCenterCurrentStep() {
			this.$nextTick(() => {
				this.centerCurrentStepIfNeeded()
			})
		},
		centerCurrentStepIfNeeded() {
			if (this.isElStepHovered || this.isElStepTouching) return
			const container = this.$refs.elStepContainer
			if (!container) return
			if (!this.deviceStatus || this.deviceStatus.length === 0) return

			const stepEls = container.querySelectorAll('.el-step')
			if (!stepEls.length) return

			let activeIndex = 0
			if (typeof this.activeStep === 'number' && this.activeStep >= 0) {
				activeIndex = Math.min(this.activeStep, stepEls.length - 1)
			}
			const activeEl = stepEls[activeIndex]
			if (!activeEl) return

			const visibleCenter = activeEl.offsetLeft - container.scrollLeft + activeEl.offsetWidth / 2
			const containerCenter = container.clientWidth / 2
			const threshold = 12

			if (Math.abs(visibleCenter - containerCenter) <= threshold) return

			let targetLeft = activeEl.offsetLeft + activeEl.offsetWidth / 2 - container.clientWidth / 2
			const maxLeft = Math.max(0, container.scrollWidth - container.clientWidth)
			targetLeft = Math.max(0, Math.min(targetLeft, maxLeft))

			container.scrollTo({
				left: targetLeft,
				behavior: 'smooth',
			})
		},
		onElStepMouseEnter() {
			this.isElStepHovered = true
			if (this.elStepMouseLeaveTimer) {
				clearTimeout(this.elStepMouseLeaveTimer)
				this.elStepMouseLeaveTimer = null
			}
		},
		onElStepMouseLeave() {
			this.isElStepHovered = false
			if (this.elStepMouseLeaveTimer) clearTimeout(this.elStepMouseLeaveTimer)
			this.elStepMouseLeaveTimer = setTimeout(() => {
				this.scheduleCenterCurrentStep()
			}, 3000)
		},
		onElStepTouchStart() {
			this.isElStepTouching = true
			if (this.elStepTouchEndTimer) {
				clearTimeout(this.elStepTouchEndTimer)
				this.elStepTouchEndTimer = null
			}
		},
		onElStepTouchMove() {
			this.isElStepTouching = true
		},
		onElStepTouchEnd() {
			if (this.elStepTouchEndTimer) clearTimeout(this.elStepTouchEndTimer)
			this.elStepTouchEndTimer = setTimeout(() => {
				this.isElStepTouching = false
				this.scheduleCenterCurrentStep()
			}, 180)
		},
	},
	mounted() {
		const rightTopBox = this.$refs.elStepContainer
		if (rightTopBox) {
			this.elStepWheelHandler = (e) => {
				e.preventDefault()
				rightTopBox.scrollLeft += e.deltaY
			}
			rightTopBox.addEventListener('wheel', this.elStepWheelHandler, { passive: false })
		}
		this.scheduleCenterCurrentStep()
	},
	beforeDestroy() {
		if (this.elStepTouchEndTimer) clearTimeout(this.elStepTouchEndTimer)
		if (this.elStepMouseLeaveTimer) clearTimeout(this.elStepMouseLeaveTimer)
		const rightTopBox = this.$refs.elStepContainer
		if (rightTopBox && this.elStepWheelHandler) {
			rightTopBox.removeEventListener('wheel', this.elStepWheelHandler)
			this.elStepWheelHandler = null
		}
	},
}
</script>