2026-04-02 16:35:45 +08:00

544 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-if="visible" class="event-dialog-overlay" @click="handleOverlayClick">
<div class="event-dialog" @click.stop>
<!-- 标题栏 -->
<div class="dialog-header">
<div class="header-title">详情</div>
<div class="close-btn" @click="handleClose">
<el-icon><Close /></el-icon>
</div>
</div>
<!-- 事件基本信息 -->
<div class="section">
<div class="section-title">
<span class="title-icon"></span>
事件基本信息
</div>
<div class="info-grid">
<div class="info-row">
<div class="info-item">
<span class="info-label">事件编号</span>
<span class="info-value">{{ eventInfo.eventNo }}</span>
</div>
<div class="info-item">
<span class="info-label">发生时间</span>
<span class="info-value">{{ eventInfo.occurTime }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">事件类型</span>
<span class="info-value">{{ eventInfo.eventType }}</span>
</div>
<div class="info-item">
<span class="info-label">事件等级</span>
<span class="info-value level-tag" :class="eventInfo.levelClass">{{ eventInfo.eventLevel }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">所属区域</span>
<span class="info-value">{{ eventInfo.region }}</span>
</div>
<div class="info-item">
<span class="info-label">上报人</span>
<span class="info-value">{{ eventInfo.reporter }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">详细地址</span>
<span class="info-value">{{ eventInfo.address }}</span>
</div>
<div class="info-item">
<span class="info-label">上报时间</span>
<span class="info-value">{{ eventInfo.reportTime }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item full-width">
<span class="info-label">事件描述</span>
<span class="info-value">{{ eventInfo.description }}</span>
</div>
</div>
</div>
</div>
<!-- 处置反馈信息 -->
<div class="section">
<div class="section-title">
<span class="title-icon"></span>
处置反馈信息
</div>
<div class="feedback-list">
<div v-for="(item, index) in feedbackList" :key="item.id" class="feedback-item">
<div class="feedback-header">
<div class="feedback-num">{{ index + 1 }}</div>
<div class="feedback-info">
<div class="feedback-row">
<span class="feedback-label">处置时间</span>
<span class="feedback-value">{{ item.handleTime }}</span>
</div>
<div class="feedback-row">
<span class="feedback-label">处置人</span>
<span class="feedback-value">{{ item.handler }}</span>
</div>
</div>
<div class="feedback-image" @click="previewImage(item.image)">
<img :src="item.image" alt="处置图片" />
</div>
</div>
<div class="feedback-detail">
<div class="detail-row">
<span class="detail-label">预计开始时间</span>
<span class="detail-value">{{ item.estimatedStartTime }}</span>
<span class="detail-label" style="margin-left: 40px">预计结束时间</span>
<span class="detail-value">{{ item.estimatedEndTime }}</span>
</div>
<div class="detail-row">
<span class="detail-label">实际开始时间</span>
<span class="detail-value">{{ item.actualStartTime }}</span>
<span class="detail-label" style="margin-left: 40px">实际结束时间</span>
<span class="detail-value">{{ item.actualEndTime }}</span>
</div>
<div class="detail-row">
<span class="detail-label">处置人</span>
<span class="detail-value">{{ item.handlerName }}</span>
<span class="detail-label" style="margin-left: 40px">联系电话</span>
<span class="detail-value">{{ item.contactPhone }}</span>
</div>
<div class="detail-row">
<span class="detail-label">处置情况描述</span>
<span class="detail-value">{{ item.handleDesc }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 图片预览弹窗 -->
<div v-if="previewVisible" class="image-preview-overlay" @click="closePreview">
<div class="image-preview-container" @click.stop>
<img :src="previewImageUrl" alt="预览" />
<div class="close-preview-btn" @click="closePreview">
<el-icon><Close /></el-icon>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, watch } from "vue";
import { Close } from "@element-plus/icons-vue";
const props = defineProps({
visible: {
type: Boolean,
default: false,
},
eventData: {
type: Object,
default: () => ({}),
},
});
const emit = defineEmits(["update:visible", "close"]);
// 事件基本信息
const eventInfo = ref({
eventNo: "202310120001",
occurTime: "2023-10-12 14:30:00",
eventType: "路面塌陷",
eventLevel: "一般事件",
levelClass: "level-normal",
region: "万州区",
reporter: "张三",
address: "万州区太白路123号附近",
reportTime: "2023-10-12 14:35:00",
description: "路面出现塌陷面积约2平方米深度约0.5米,已设置警示标志,请尽快处理。",
});
// 处置反馈信息
const feedbackList = ref([
{
id: 1,
handleTime: "2023-10-12 14:45:26",
handler: "李四",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=图片1",
estimatedStartTime: "2023-10-12 14:30:00",
estimatedEndTime: "2023-10-12 16:30:00",
actualStartTime: "2023-10-12 14:45:00",
actualEndTime: "2023-10-12 16:20:00",
handlerName: "王五",
contactPhone: "13800138000",
handleDesc: "已到达现场,正在设置围挡,准备进行修复作业。",
},
{
id: 2,
handleTime: "2023-10-12 16:20:45",
handler: "李四",
image: "https://via.placeholder.com/80x60/40a9ff/ffffff?text=图片2",
estimatedStartTime: "2023-10-12 14:30:00",
estimatedEndTime: "2023-10-12 16:30:00",
actualStartTime: "2023-10-12 14:45:00",
actualEndTime: "2023-10-12 16:20:00",
handlerName: "王五",
contactPhone: "13800138000",
handleDesc: "修复作业已完成,路面已恢复平整,围挡已拆除,交通恢复正常。",
},
]);
// 图片预览
const previewVisible = ref(false);
const previewImageUrl = ref("");
const previewImage = (url) => {
previewImageUrl.value = url;
previewVisible.value = true;
};
const closePreview = () => {
previewVisible.value = false;
previewImageUrl.value = "";
};
// 关闭对话框
const handleClose = () => {
emit("update:visible", false);
emit("close");
};
// 点击遮罩关闭
const handleOverlayClick = () => {
handleClose();
};
// 监听visible变化
watch(
() => props.visible,
(newVal) => {
if (newVal && props.eventData) {
// 如果有传入数据,更新显示
Object.assign(eventInfo.value, props.eventData);
}
}
);
</script>
<style lang="scss" scoped>
.event-dialog-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
align-items: center;
justify-content: center;
z-index: 2100;
}
.event-dialog {
width: 80vw;
max-width: 700px;
max-height: 85vh;
overflow-y: auto;
background: linear-gradient(135deg, rgba(20, 50, 90, 0.95) 0%, rgba(10, 30, 60, 0.98) 100%);
border: 1px solid rgba(64, 169, 255, 0.3);
border-radius: 12px;
padding: 24px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}
// 标题栏
.dialog-header {
display: flex;
align-items: center;
justify-content: center;
position: relative;
margin-bottom: 24px;
.header-title {
font-size: 20px;
font-weight: 600;
color: #fff;
padding: 8px 40px;
background: linear-gradient(90deg, transparent 0%, rgba(64, 169, 255, 0.2) 20%, rgba(64, 169, 255, 0.2) 80%, transparent 100%);
border-bottom: 2px solid #40a9ff;
}
.close-btn {
position: absolute;
right: 0;
top: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.7);
cursor: pointer;
font-size: 20px;
transition: color 0.3s;
&:hover {
color: #fff;
}
}
}
// 区块
.section {
margin-bottom: 24px;
&:last-child {
margin-bottom: 0;
}
}
// 区块标题
.section-title {
font-size: 16px;
font-weight: 600;
color: #fff;
margin-bottom: 16px;
display: flex;
align-items: center;
.title-icon {
color: #40a9ff;
margin-right: 8px;
}
}
// 信息网格
.info-grid {
background-color: rgba(30, 70, 120, 0.3);
border-radius: 8px;
padding: 16px 20px;
}
.info-row {
display: flex;
margin-bottom: 12px;
&:last-child {
margin-bottom: 0;
}
}
.info-item {
flex: 1;
display: flex;
align-items: flex-start;
&.full-width {
flex: none;
width: 100%;
}
}
.info-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
white-space: nowrap;
min-width: 70px;
}
.info-value {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
flex: 1;
word-break: break-all;
&.level-tag {
display: inline-block;
padding: 2px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
&.level-urgent {
background-color: rgba(255, 77, 79, 0.2);
color: #ff4d4f;
border: 1px solid rgba(255, 77, 79, 0.4);
}
&.level-normal {
background-color: rgba(64, 169, 255, 0.2);
color: #40a9ff;
border: 1px solid rgba(64, 169, 255, 0.4);
}
&.level-low {
background-color: rgba(82, 196, 26, 0.2);
color: #52c41a;
border: 1px solid rgba(82, 196, 26, 0.4);
}
}
}
// 反馈列表
.feedback-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.feedback-item {
background-color: rgba(30, 70, 120, 0.3);
border-radius: 8px;
padding: 16px 20px;
border-left: 3px solid #40a9ff;
}
.feedback-header {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
}
.feedback-num {
width: 24px;
height: 24px;
background: linear-gradient(135deg, #40a9ff 0%, #1890ff 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
color: #fff;
margin-right: 12px;
flex-shrink: 0;
}
.feedback-info {
flex: 1;
}
.feedback-row {
margin-bottom: 6px;
&:last-child {
margin-bottom: 0;
}
}
.feedback-label {
font-size: 13px;
color: rgba(255, 255, 255, 0.6);
}
.feedback-value {
font-size: 13px;
color: rgba(255, 255, 255, 0.9);
}
.feedback-image {
width: 80px;
height: 60px;
border-radius: 4px;
overflow: hidden;
cursor: pointer;
border: 1px solid rgba(64, 169, 255, 0.3);
transition: all 0.3s;
&:hover {
border-color: #40a9ff;
transform: scale(1.05);
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
// 反馈详情
.feedback-detail {
padding-left: 36px;
padding-top: 12px;
border-top: 1px solid rgba(64, 169, 255, 0.1);
}
.detail-row {
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
}
.detail-label {
font-size: 12px;
color: rgba(255, 255, 255, 0.5);
}
.detail-value {
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
}
// 图片预览
.image-preview-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.85);
display: flex;
align-items: center;
justify-content: center;
z-index: 1100;
}
.image-preview-container {
position: relative;
max-width: 80%;
max-height: 80%;
img {
max-width: 100%;
max-height: 80vh;
border-radius: 8px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}
}
.close-preview-btn {
position: absolute;
top: -40px;
right: 0;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
font-size: 24px;
transition: color 0.3s;
&:hover {
color: #fff;
}
}
// 隐藏滚动条
.event-dialog {
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
</style>