feat: 冰灾调整

This commit is contained in:
niedongsheng 2026-04-20 16:13:03 +08:00
parent c850d60368
commit bf86b7d073
6 changed files with 159 additions and 754 deletions

View File

@ -7,6 +7,7 @@
class="inner-input"
v-model="modelValue"
:placeholder="placeholder"
@input="search"
/>
<van-icon
class="close-icon"
@ -35,9 +36,21 @@ const props = defineProps({
}
})
const emit = defineEmits(['search'])
let timer = null
//
const search = () => {
clearTimeout(timer)
timer = setTimeout(() => {
emit('search', modelValue.value)
}, 1000)
}
//
const clearInput = () => {
modelValue.value = ''
emit('search', modelValue.value)
}
</script>

View File

@ -36,8 +36,8 @@ const route = useRoute()
const isContinue = computed(() => route.query.isContinue)
const title = computed(() => {
const label = route.query.eventType === 'ice' ? '冰毁' : '水毁'
if(!isContinue) return `${label}填报`
const label = eventType.value === 'ice' ? '冰毁' : '水毁'
if(!isContinue.value) return `${label}填报`
return `${label}续报`
})

View File

@ -46,22 +46,24 @@
</PanelItem>
<PanelItem title="处置情况">
<van-field label="处置措施">
<van-field label="处置措施" label-align="top">
<template #input>
<van-col
v-for="(item, index) in options['iceDisposalMeasures']"
:span="24 / options['iceDisposalMeasures'].length"
:key="index"
>
<van-button
block
plain
:type="item.value === formData.report.disposalMeasures ? 'primary' : 'default'"
@click="formData.report.disposalMeasures = item.value"
<van-row :gutter="5">
<van-col
v-for="(item, index) in options['iceDisposalMeasures']"
:span="8"
:key="index"
>
{{ item.label }}
</van-button>
</van-col>
<van-button
block
plain
:type="item.value === formData.report.disposalMeasures ? 'primary' : 'default'"
@click="formData.report.disposalMeasures = item.value"
>
{{ item.label }}
</van-button>
</van-col>
</van-row>
</template>
</van-field>
@ -155,7 +157,7 @@ import { request } from '@shared/utils/request';
import { useOptions } from '@shared/composables/useOptions';
import DisasterFileUpload from '../components/DisasterFileUpload.vue';
import { showToast, showFailToast, showLoadingToast, showSuccessToast } from 'vant';
import { formatDate } from '@shared/utils'
import { formatDate } from '@shared/utils';
const route = useRoute();
const { options } = useOptions();
@ -222,17 +224,16 @@ const calibrateTime = isShowToast => {
};
const validate = () => {
return true
}
return true;
};
const submitting = ref(false)
const submitting = ref(false);
const handleSubmit = async () => {
//
if (!validate()) return;
submitting.value = true;
try {
//
const submitData = {
...formData.value,
@ -262,7 +263,7 @@ const handleSubmit = async () => {
} else {
//
setTimeout(() => {
if(isContinue) router.go(-1)
if (isContinue) router.go(-1);
else router.replace('/disasterManagement');
}, 500);
}
@ -276,7 +277,7 @@ const handleSubmit = async () => {
submitting.value = false;
}
};
const detailData = ref(null)
const detailData = ref(null);
const getDisasterDetail = async () => {
const id = route.query.id;
if (!id) {
@ -295,12 +296,12 @@ const getDisasterDetail = async () => {
if (result?.data) {
const data = result.data;
data.reportList = undefined
data.report = {}
data.yhzMaterialList = []
data.fileList = []
data.reportList = undefined;
data.report = {};
data.yhzMaterialList = [];
data.fileList = [];
detailData.value = data;
formData.value = data
formData.value = data;
} else {
ElMessage.warning(result.message || '获取详情失败');
}

View File

@ -1,535 +0,0 @@
<template>
<PageContainer title="冰毁详情" @click-back="handleClickBack" class="page-container">
<!-- 当前站点信息 -->
<CurrentSite />
<!-- 基本信息 -->
<PanelItem title="基本信息" v-if="!loading">
<template #headerExtra>
<div class="status-wrapper">
<van-tag :type="getEventStatusType()" size="medium" plain>
{{ getEventStatusText() }}
</van-tag>
</div>
</template>
<!-- 事件类型 -->
<div class="info-row">
<span class="info-label">事件类型</span>
<span class="info-value">冰毁事件</span>
</div>
<!-- 路况类别 -->
<div class="info-row">
<span class="info-label">路况类别</span>
<span class="info-value">{{ detailData.roadConditionType || '-' }}</span>
</div>
<!-- 是否阻断 -->
<div class="info-row">
<span class="info-label">是否阻断</span>
<span class="info-value">{{ detailData.event?.isBlocked ? '是' : '否' }}</span>
</div>
<!-- 抢险进度 -->
<div class="info-row">
<span class="info-label">抢险进度</span>
<span class="info-value">{{ detailData.event?.repairProgress || '-' }}</span>
</div>
<!-- <div class="info-row">
<span class="info-label">处理措施</span>
<span class="info-value">{{ formatDisposalMeasures(detailData.event?.disposalMeasures) || '-' }}</span>
</div> -->
<!-- 水毁处数 -->
<div class="info-row">
<span class="info-label">水毁处数</span>
<span class="info-value">{{ detailData.event?.damageCount || 0 }}</span>
</div>
<!-- 阻断里程 -->
<div class="info-row">
<span class="info-label">阻断里程</span>
<span class="info-value">{{ detailData.event?.blockedMileage ? detailData.event.blockedMileage + '公里' : '-' }}</span>
</div>
<!-- 发生时间 -->
<div class="info-row">
<span class="info-label">发生时间</span>
<span class="info-value">{{ detailData.occurTime || '-' }}</span>
</div>
<!-- 线路编号 -->
<div class="info-row">
<span class="info-label">线路编号</span>
<span class="info-value">{{ detailData.routeNo || '-' }}</span>
</div>
<!-- 地点路线 -->
<div class="info-row">
<span class="info-label">地点路线</span>
<span class="info-value">{{ detailData.occurLocation || '-' }}</span>
</div>
<!-- 起点桩号 -->
<div class="info-row">
<span class="info-label">起点桩号</span>
<span class="info-value">{{ detailData.event?.startStakeNo || '-' }}</span>
</div>
<!-- 止点桩号 -->
<div class="info-row">
<span class="info-label">止点桩号</span>
<span class="info-value">{{ detailData.event?.endStakeNo || '-' }}</span>
</div>
<!-- 路况位置使用阻断点小地名或发生地点 -->
<div class="info-row">
<span class="info-label">路况位置</span>
<span class="info-value">{{ detailData.event?.blockedPointName || detailData.occurLocation || '-' }}</span>
</div>
<!-- 阻断点小地名 -->
<div class="info-row">
<span class="info-label">阻断点小地名</span>
<span class="info-value">{{ detailData.event?.blockedPointName || '-' }}</span>
</div>
<!-- 上报区县 -->
<div class="info-row">
<span class="info-label">上报区县</span>
<span class="info-value">{{ detailData.event?.district || '-' }}</span>
</div>
<!-- 是否恢复重建 -->
<div class="info-row">
<span class="info-label">是否恢复重建</span>
<span class="info-value">{{ detailData.event?.needsRecovery ? '是' : '否' }}</span>
</div>
<!-- 恢复重建预估费用 -->
<div class="info-row">
<span class="info-label">恢复重建预估费用</span>
<span class="info-value">{{ detailData.event?.estimatedRecoveryCost ? detailData.event.estimatedRecoveryCost + '万元' : '-' }}</span>
</div>
<!-- 联系人 -->
<div class="info-row">
<span class="info-label">联系人</span>
<span class="info-value">{{ detailData.event?.contactPerson || '-' }}</span>
</div>
<!-- 联系电话 -->
<div class="info-row">
<span class="info-label">联系电话</span>
<span class="info-value">{{ detailData.event?.contactPhone || '-' }}</span>
</div>
<!-- 填报单位 -->
<div class="info-row">
<span class="info-label">填报单位</span>
<span class="info-value">{{ detailData.event?.reporterUnit || '-' }}</span>
</div>
</PanelItem>
<!-- 填报信息 -->
<PanelItem title="填报信息" v-if="!loading">
<!-- 遍历所有填报记录首报 + 续报 -->
<div v-for="(report, index) in allReports" :key="index" class="report-section">
<div class="report-header">
<span class="report-title">{{ report?.title }}</span>
<span class="report-meta">{{ report.reporterName || '-' }} {{ report.reportTime || '-' }}</span>
</div>
<div class="report-content">
<div class="info-row">
<span class="info-label">处置措施</span>
<span class="info-value">{{ report.disposalMeasures || '-' }}</span>
</div>
<template v-for="(lossItem, idx) of report.lossList" :key="idx">
<div class="info-row">
<span class="info-label">{{ lossItem.lossCategory }}</span>
<span class="info-value">{{ lossItem.totalAmount }}{{ lossItem.unit }}</span>
</div>
<div class="info-row" v-if="lossItem.lossCategory == '其他损失'">
<span class="info-label">其它损失描述</span>
<span class="info-value">{{ lossItem.remark }}</span>
</div>
</template>
<div class="info-row">
<span class="info-label">有无车辆滞留</span>
<span class="info-value">{{ getVehicleStrandedText(report) }}</span>
</div>
<div class="info-row">
<span class="info-label">滞留车辆</span>
<span class="info-value">{{ report.strandedVehicleCount || 0 }}</span>
</div>
<div class="info-row">
<span class="info-label">预计恢复时间</span>
<span class="info-value">{{ report.expectRecoverTime || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">实际恢复时间</span>
<span class="info-value">{{ report.actualRecoverTime || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">现场描述</span>
<span class="info-value">{{ report.siteDescription || '-' }}</span>
</div>
<!-- 附件 -->
<div class="info-row column" v-if="report.fileList && report.fileList.length > 0">
<span class="info-label">附件</span>
<div class="attachment-list">
<div v-for="(file, fileIndex) in report.fileList" :key="fileIndex" class="attachment-item">
<div class="preview-image-block" v-if="file.fileType === 1" @click="previewFile(report, file)">
<img :src="file.fileUrl" alt="" />
</div>
<div class="preview-video-block" v-else>
<van-icon :name="file.fileType === 1 ? 'photo-o' : 'video-o'" />
<span class="file-name">{{ file.fileName }}</span>
<!-- <van-button size="mini" type="primary" plain @click="previewFile(report, file)">预览</van-button> -->
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 无填报信息时显示 -->
<EmptyBox v-if="!hasReportData" placeholder="暂无填报信息" />
</PanelItem>
<!-- 底部按钮未解除状态显示续报按钮 -->
<div class="footer-buttons" v-if="!loading">
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
</div>
<van-loading class="loading-icon" v-if="loading">加载中...</van-loading>
<van-image-preview :startPosition="startPosition" v-model:show="previewImagesVisible" :images="imagesForPreview">
<template v-slot:index="{ index }">{{ index + 1 }}</template>
</van-image-preview>
</PageContainer>
</template>
<script setup>
import { onMounted, ref, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { showToast, showImagePreview } from 'vant'
import PageContainer from '@/components/PageContainer.vue'
import PanelItem from '@/components/PanelItem.vue'
import CurrentSite from '@/components/CurrentSite.vue'
import EmptyBox from '@/components/EmptyBox.vue'
import { request } from '@shared/utils/request'
const router = useRouter()
const route = useRoute()
// Data
const detailData = ref({
event: null, // Event
report: [], //
fileList: [], //
lossList: [], //
occurLocation: '',
occurTime: '',
roadConditionType: '',
routeNo: ''
})
const loading = ref(true)
const allReports = computed(() => {
const reports =
detailData.value.report?.map((item, index) => {
if (index === detailData.value.report.length - 1) {
item.title = '首报'
} else {
item.title = '续报' + (detailData.value.report.length - 1 - index)
}
return item
}) || []
return reports
// return reports.reverse()
})
//
const hasReportData = computed(() => {
return allReports.value.length > 0
})
//
const getEventStatusText = () => {
return detailData.eventStatus === 1 ? '已解除' : '未解除'
}
//
const getEventStatusType = () => {
return detailData.eventStatus === 1 ? 'success' : 'danger'
}
//
const formatDisposalMeasures = (measures) => {
if (!measures) return ''
const measureMap = {
半幅封闭: '半幅封闭',
全副封闭: '全副封闭',
便道通行: '便道通行',
正常通行: '正常通行'
}
return measures
.split(',')
.map((m) => measureMap[m.trim()] || m.trim())
.join('、')
}
// lossList
const getLossDescription = (report) => {
const lossList = report?.lossList
if (!lossList || lossList.length === 0) return '-'
const totalVolume = lossList.reduce((sum, loss) => {
const volume = (loss.length || 0) * (loss.width || 0) * (loss.height || 0)
return sum + volume
}, 0)
const totalAmount = lossList.reduce((sum, loss) => sum + (loss.totalAmount || 0), 0)
return `${totalVolume}方,共损失${totalAmount}万元`
}
//
const getVehicleStrandedText = (report) => {
const count = report?.strandedVehicleCount || 0
return count > 0 ? `有车滞留` : '无车滞留'
}
//
const getDisasterDetail = async () => {
const id = route.query.id
if (!id) {
showToast('缺少灾毁ID')
return
}
loading.value = true
try {
const result = await request({
url: `/snow-ops-platform/event/getById`,
method: 'get',
params: { id }
})
if (result?.data) {
// Data
const data = result.data
detailData.value = {
event: data.event || null,
report: data.reportList || [], // 使 report
fileList: data.fileList || [],
lossList: data.lossList || [],
occurLocation: data.occurLocation || '',
occurTime: data.occurTime || '',
roadConditionType: data.roadConditionType || '',
routeNo: data.routeNo || ''
}
} else {
showToast(result.message || '获取详情失败')
}
} catch (error) {
console.error('获取灾毁详情失败:', error)
showToast('获取详情失败,请稍后重试')
}
loading.value = false
}
//
const handleClickBack = () => {
router.push('/disasterManagement')
}
//
const handleContinueReport = () => {
router.push({
path: '/disasterReport',
query: {
id: route.query.id,
eventType: 'ice',
isContinue: 'true'
}
})
}
const isImageFile = (file) => {
// url
const imageExtensions = /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i
if (file.fileUrl && imageExtensions.test(file.fileUrl)) return true
//
if (file.type && file.type.startsWith('image/')) return true
return false
}
const imagesForPreview = ref([])
const previewImagesVisible = ref(false)
const startPosition = ref(0)
//
const previewFile = (report, file) => {
const images = report.fileList.filter((file) => isImageFile(file))
imagesForPreview.value = images.map((item) => item.fileUrl)
startPosition.value = imagesForPreview.value.indexOf(file.fileUrl)
previewImagesVisible.value = true
}
onMounted(() => {
getDisasterDetail()
})
</script>
<style scoped lang="scss">
.page-container {
padding-bottom: 80px;
}
.status-wrapper {
border-bottom: 1px solid #ebedf0;
}
.info-row {
display: flex;
align-items: flex-start;
margin-bottom: 12px;
line-height: 1.4;
&.sub-row {
margin-left: 20px;
margin-top: -8px;
}
&.column {
flex-direction: column;
.info-label {
margin-bottom: 10px;
}
}
}
.info-label {
width: 110px;
flex-shrink: 0;
color: #969799;
font-size: 14px;
}
.info-value {
flex: 1;
color: #323233;
font-size: 14px;
word-break: break-all;
}
.report-section {
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #ebedf0;
&:last-child {
border-bottom: none;
margin-bottom: 0;
}
}
.report-header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px dashed #ebedf0;
.report-title {
font-size: 16px;
font-weight: 500;
color: #1989fa;
}
.report-meta {
font-size: 12px;
color: #969799;
}
}
.report-content {
.info-row {
margin-bottom: 10px;
}
}
.attachment-list {
display: flex;
flex-wrap: wrap;
flex: 1;
gap: 10px;
overflow: hidden;
.attachment-item {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
background: #f7f8fa;
border-radius: 4px;
.van-icon {
font-size: 20px;
color: #1989fa;
}
.file-name {
flex: 1;
font-size: 13px;
color: #323233;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
.preview-image-block {
width: 60px;
height: 60px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.footer-buttons {
position: fixed;
bottom: 0;
left: 0;
right: 0;
display: flex;
gap: 12px;
padding: 12px 16px;
background: #fff;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
z-index: 10;
.footer-btn {
flex: 1;
height: 44px;
border-radius: 22px;
font-size: 16px;
}
}
.loading-icon {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

View File

@ -19,39 +19,16 @@
<span class="info-value">冰毁事件</span>
</div>
<!-- 路况类别 -->
<!-- 所属服务站 -->
<div class="info-row">
<span class="info-label">路况类别</span>
<span class="info-value">{{ detailData.roadConditionType || '-' }}</span>
<span class="info-label">所属服务站</span>
<span class="info-value">{{ detailData.event?.stationName || '-' }}</span>
</div>
<!-- 是否阻断 -->
<!-- 线路编号 -->
<div class="info-row">
<span class="info-label">是否阻断</span>
<span class="info-value">{{ detailData.event?.isBlocked ? '是' : '否' }}</span>
</div>
<!-- 抢险进度 -->
<div class="info-row">
<span class="info-label">抢险进度</span>
<span class="info-value">{{ detailData.event?.repairProgress || '-' }}</span>
</div>
<!-- <div class="info-row">
<span class="info-label">处理措施</span>
<span class="info-value">{{ formatDisposalMeasures(detailData.event?.disposalMeasures) || '-' }}</span>
</div> -->
<!-- 水毁处数 -->
<div class="info-row">
<span class="info-label">水毁处数</span>
<span class="info-value">{{ detailData.event?.damageCount || 0 }}</span>
</div>
<!-- 阻断里程 -->
<div class="info-row">
<span class="info-label">阻断里程</span>
<span class="info-value">{{ detailData.event?.blockedMileage ? detailData.event.blockedMileage + '公里' : '-' }}</span>
<span class="info-label">线路编号</span>
<span class="info-value">{{ detailData.routeNo || '-' }}</span>
</div>
<!-- 发生时间 -->
@ -60,18 +37,18 @@
<span class="info-value">{{ detailData.occurTime || '-' }}</span>
</div>
<!-- 线路编号 -->
<div class="info-row">
<span class="info-label">线路编号</span>
<span class="info-value">{{ detailData.routeNo || '-' }}</span>
</div>
<!-- 地点路线 -->
<div class="info-row">
<span class="info-label">地点路线</span>
<span class="info-label">路况位置</span>
<span class="info-value">{{ detailData.occurLocation || '-' }}</span>
</div>
<!-- 发生地点 -->
<div class="info-row">
<span class="info-label">发生地点</span>
<span class="info-value">{{ detailData.event?.occurLocation || '-' }}</span>
</div>
<!-- 起点桩号 -->
<div class="info-row">
<span class="info-label">起点桩号</span>
@ -83,54 +60,6 @@
<span class="info-label">止点桩号</span>
<span class="info-value">{{ detailData.event?.endStakeNo || '-' }}</span>
</div>
<!-- 路况位置使用阻断点小地名或发生地点 -->
<div class="info-row">
<span class="info-label">路况位置</span>
<span class="info-value">{{ detailData.event?.blockedPointName || detailData.occurLocation || '-' }}</span>
</div>
<!-- 阻断点小地名 -->
<div class="info-row">
<span class="info-label">阻断点小地名</span>
<span class="info-value">{{ detailData.event?.blockedPointName || '-' }}</span>
</div>
<!-- 上报区县 -->
<div class="info-row">
<span class="info-label">上报区县</span>
<span class="info-value">{{ detailData.event?.district || '-' }}</span>
</div>
<!-- 是否恢复重建 -->
<div class="info-row">
<span class="info-label">是否恢复重建</span>
<span class="info-value">{{ detailData.event?.needsRecovery ? '是' : '否' }}</span>
</div>
<!-- 恢复重建预估费用 -->
<div class="info-row">
<span class="info-label">恢复重建预估费用</span>
<span class="info-value">{{ detailData.event?.estimatedRecoveryCost ? detailData.event.estimatedRecoveryCost + '万元' : '-' }}</span>
</div>
<!-- 联系人 -->
<div class="info-row">
<span class="info-label">联系人</span>
<span class="info-value">{{ detailData.event?.contactPerson || '-' }}</span>
</div>
<!-- 联系电话 -->
<div class="info-row">
<span class="info-label">联系电话</span>
<span class="info-value">{{ detailData.event?.contactPhone || '-' }}</span>
</div>
<!-- 填报单位 -->
<div class="info-row">
<span class="info-label">填报单位</span>
<span class="info-value">{{ detailData.event?.reporterUnit || '-' }}</span>
</div>
</PanelItem>
<!-- 填报信息 -->
@ -139,21 +68,28 @@
<div v-for="(report, index) in allReports" :key="index" class="report-section">
<div class="report-header">
<span class="report-title">{{ report?.title }}</span>
<span class="report-meta">{{ report.reporterName || '-' }} {{ report.reportTime || '-' }}</span>
<span class="report-meta">
{{ report.reporterName || '-' }} {{ report.reportTime || '-' }}
</span>
</div>
<div class="report-content">
<div class="info-row">
<span class="info-label">处置措施</span>
<span class="info-value">{{ report.disposalMeasures || '-' }}</span>
</div>
<template v-for="(lossItem, idx) of report.lossList" :key="idx">
<div class="info-row">
<span class="info-label">预计恢复时间</span>
<span class="info-value">{{ report.expectRecoverTime || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">实际恢复时间</span>
<span class="info-value">{{ report.actualRecoverTime || '-' }}</span>
</div>
<template v-for="(item, idx) of report.materialUsageList" :key="idx">
<div class="info-row">
<span class="info-label">{{ lossItem.lossCategory }}</span>
<span class="info-value">{{ lossItem.totalAmount }}{{ lossItem.unit }}</span>
</div>
<div class="info-row" v-if="lossItem.lossCategory == '其他损失'">
<span class="info-label">其它损失描述</span>
<span class="info-value">{{ lossItem.remark }}</span>
<span class="info-label">{{ item.materialName }}</span>
<span class="info-value" v-if="item.usageAmount">{{ item.usageAmount + '' + item.materialUnit }}</span>
<span class="info-value" v-else>-</span>
</div>
</template>
<div class="info-row">
@ -164,14 +100,6 @@
<span class="info-label">滞留车辆</span>
<span class="info-value">{{ report.strandedVehicleCount || 0 }}</span>
</div>
<div class="info-row">
<span class="info-label">预计恢复时间</span>
<span class="info-value">{{ report.expectRecoverTime || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">实际恢复时间</span>
<span class="info-value">{{ report.actualRecoverTime || '-' }}</span>
</div>
<div class="info-row">
<span class="info-label">现场描述</span>
<span class="info-value">{{ report.siteDescription || '-' }}</span>
@ -180,8 +108,16 @@
<div class="info-row column" v-if="report.fileList && report.fileList.length > 0">
<span class="info-label">附件</span>
<div class="attachment-list">
<div v-for="(file, fileIndex) in report.fileList" :key="fileIndex" class="attachment-item">
<div class="preview-image-block" v-if="file.fileType === 1" @click="previewFile(report, file)">
<div
v-for="(file, fileIndex) in report.fileList"
:key="fileIndex"
class="attachment-item"
>
<div
class="preview-image-block"
v-if="file.fileType === 1"
@click="previewFile(report, file)"
>
<img :src="file.fileUrl" alt="" />
</div>
<div class="preview-video-block" v-else>
@ -206,24 +142,28 @@
<van-loading class="loading-icon" v-if="loading">加载中...</van-loading>
<van-image-preview :startPosition="startPosition" v-model:show="previewImagesVisible" :images="imagesForPreview">
<van-image-preview
:startPosition="startPosition"
v-model:show="previewImagesVisible"
:images="imagesForPreview"
>
<template v-slot:index="{ index }">{{ index + 1 }}</template>
</van-image-preview>
</PageContainer>
</template>
<script setup>
import { onMounted, ref, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { showToast, showImagePreview } from 'vant'
import PageContainer from '@/components/PageContainer.vue'
import PanelItem from '@/components/PanelItem.vue'
import CurrentSite from '@/components/CurrentSite.vue'
import EmptyBox from '@/components/EmptyBox.vue'
import { request } from '@shared/utils/request'
import { onMounted, ref, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { showToast, showImagePreview } from 'vant';
import PageContainer from '@/components/PageContainer.vue';
import PanelItem from '@/components/PanelItem.vue';
import CurrentSite from '@/components/CurrentSite.vue';
import EmptyBox from '@/components/EmptyBox.vue';
import { request } from '@shared/utils/request';
const router = useRouter()
const route = useRoute()
const router = useRouter();
const route = useRoute();
// Data
const detailData = ref({
@ -234,120 +174,106 @@ const detailData = ref({
occurLocation: '',
occurTime: '',
roadConditionType: '',
routeNo: ''
})
routeNo: '',
});
const loading = ref(true)
const loading = ref(true);
const allReports = computed(() => {
const reports =
detailData.value.report?.map((item, index) => {
if (index === detailData.value.report.length - 1) {
item.title = '首报'
item.title = '首报';
} else {
item.title = '续报' + (detailData.value.report.length - 1 - index)
item.title = '续报' + (detailData.value.report.length - 1 - index);
}
return item
}) || []
return reports
return item;
}) || [];
return reports;
// return reports.reverse()
})
});
//
const hasReportData = computed(() => {
return allReports.value.length > 0
})
return allReports.value.length > 0;
});
//
const getEventStatusText = () => {
return detailData.eventStatus === 1 ? '已解除' : '未解除'
}
return detailData.eventStatus === 1 ? '已解除' : '未解除';
};
//
const getEventStatusType = () => {
return detailData.eventStatus === 1 ? 'success' : 'danger'
}
return detailData.eventStatus === 1 ? 'success' : 'danger';
};
//
const formatDisposalMeasures = (measures) => {
if (!measures) return ''
const formatDisposalMeasures = measures => {
if (!measures) return '';
const measureMap = {
半幅封闭: '半幅封闭',
全副封闭: '全副封闭',
便道通行: '便道通行',
正常通行: '正常通行'
}
正常通行: '正常通行',
};
return measures
.split(',')
.map((m) => measureMap[m.trim()] || m.trim())
.join('、')
}
.map(m => measureMap[m.trim()] || m.trim())
.join('、');
};
// lossList
const getLossDescription = (report) => {
const lossList = report?.lossList
if (!lossList || lossList.length === 0) return '-'
const totalVolume = lossList.reduce((sum, loss) => {
const volume = (loss.length || 0) * (loss.width || 0) * (loss.height || 0)
return sum + volume
}, 0)
const totalAmount = lossList.reduce((sum, loss) => sum + (loss.totalAmount || 0), 0)
return `${totalVolume}方,共损失${totalAmount}万元`
}
//
const getVehicleStrandedText = (report) => {
const count = report?.strandedVehicleCount || 0
return count > 0 ? `有车滞留` : '无车滞留'
}
const getVehicleStrandedText = report => {
const count = report?.strandedVehicleCount || 0;
return count > 0 ? `有车滞留` : '无车滞留';
};
//
const getDisasterDetail = async () => {
const id = route.query.id
const id = route.query.id;
if (!id) {
showToast('缺少灾毁ID')
return
showToast('缺少灾毁ID');
return;
}
loading.value = true
loading.value = true;
try {
const result = await request({
url: `/snow-ops-platform/event/getById`,
method: 'get',
params: { id }
})
params: { id },
});
if (result?.data) {
// Data
const data = result.data
const data = result.data;
detailData.value = {
event: data.event || null,
report: data.reportList || [], // 使 report
report: data.reportList?.reverse() || [], // 使 report
fileList: data.fileList || [],
lossList: data.lossList || [],
occurLocation: data.occurLocation || '',
occurTime: data.occurTime || '',
roadConditionType: data.roadConditionType || '',
routeNo: data.routeNo || ''
}
routeNo: data.routeNo || '',
};
} else {
showToast(result.message || '获取详情失败')
showToast(result.message || '获取详情失败');
}
} catch (error) {
console.error('获取灾毁详情失败:', error)
showToast('获取详情失败,请稍后重试')
console.error('获取灾毁详情失败:', error);
showToast('获取详情失败,请稍后重试');
}
loading.value = false
}
loading.value = false;
};
//
const handleClickBack = () => {
router.push('/disasterManagement')
}
router.push('/disasterManagement');
};
//
const handleContinueReport = () => {
@ -356,35 +282,35 @@ const handleContinueReport = () => {
query: {
id: route.query.id,
eventType: 'ice',
isContinue: 'true'
}
})
}
isContinue: 'true',
},
});
};
const isImageFile = (file) => {
const isImageFile = file => {
// url
const imageExtensions = /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i
if (file.fileUrl && imageExtensions.test(file.fileUrl)) return true
const imageExtensions = /\.(jpg|jpeg|png|gif|webp|bmp|svg)$/i;
if (file.fileUrl && imageExtensions.test(file.fileUrl)) return true;
//
if (file.type && file.type.startsWith('image/')) return true
return false
}
if (file.type && file.type.startsWith('image/')) return true;
return false;
};
const imagesForPreview = ref([])
const previewImagesVisible = ref(false)
const startPosition = ref(0)
const imagesForPreview = ref([]);
const previewImagesVisible = ref(false);
const startPosition = ref(0);
//
const previewFile = (report, file) => {
const images = report.fileList.filter((file) => isImageFile(file))
imagesForPreview.value = images.map((item) => item.fileUrl)
startPosition.value = imagesForPreview.value.indexOf(file.fileUrl)
previewImagesVisible.value = true
}
const images = report.fileList.filter(file => isImageFile(file));
imagesForPreview.value = images.map(item => item.fileUrl);
startPosition.value = imagesForPreview.value.indexOf(file.fileUrl);
previewImagesVisible.value = true;
};
onMounted(() => {
getDisasterDetail()
})
getDisasterDetail();
});
</script>
<style scoped lang="scss">

View File

@ -26,7 +26,7 @@
<el-col :span="8">
<div class="info-item">
<span class="info-label">线路编号</span>
<span class="info-value">{{ detailData.routeNo || detailData.event?.routeNo || '-' }}</span>
<span class="info-value">{{ detailData.routeNo || '-' }}</span>
</div>
</el-col>
</el-row>