Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
@ -6,7 +6,6 @@
|
|||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<PanelItem title="基本信息">
|
<PanelItem title="基本信息">
|
||||||
<template #headerExtra>
|
<template #headerExtra>
|
||||||
<!-- 状态标签(需要从续报中判断是否已解除,或接口增加 eventStatus 字段) -->
|
|
||||||
<div class="status-wrapper">
|
<div class="status-wrapper">
|
||||||
<van-tag :type="getEventStatusType()" size="medium" plain>
|
<van-tag :type="getEventStatusType()" size="medium" plain>
|
||||||
{{ getEventStatusText() }}
|
{{ getEventStatusText() }}
|
||||||
@ -38,11 +37,10 @@
|
|||||||
<span class="info-value">{{ detailData.event?.repairProgress || '-' }}</span>
|
<span class="info-value">{{ detailData.event?.repairProgress || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 处理措施(从首报中获取) -->
|
<!-- <div class="info-row">
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">处理措施:</span>
|
<span class="info-label">处理措施:</span>
|
||||||
<span class="info-value">{{ formatDisposalMeasures(firstReport?.disposalMeasures) || '-' }}</span>
|
<span class="info-value">{{ formatDisposalMeasures(detailData.event?.disposalMeasures) || '-' }}</span>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<!-- 水毁处数 -->
|
<!-- 水毁处数 -->
|
||||||
<div class="info-row">
|
<div class="info-row">
|
||||||
@ -159,63 +157,10 @@
|
|||||||
|
|
||||||
<!-- 填报信息 -->
|
<!-- 填报信息 -->
|
||||||
<PanelItem title="填报信息">
|
<PanelItem title="填报信息">
|
||||||
<!-- 首报信息 -->
|
<!-- 遍历所有填报记录(首报 + 续报) -->
|
||||||
<div class="report-section" v-if="firstReport">
|
<div v-for="(report, index) in allReports" :key="index" class="report-section">
|
||||||
<div class="report-header">
|
<div class="report-header">
|
||||||
<span class="report-title">首报</span>
|
<span class="report-title">{{ report?.title }}</span>
|
||||||
<span class="report-meta">{{ firstReport.reporterName || '-' }} {{ firstReport.reportTime || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="report-content">
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">处置情况:</span>
|
|
||||||
<span class="info-value">{{ formatDisposalMeasures(firstReport.disposalMeasures) || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">塌方及损失:</span>
|
|
||||||
<span class="info-value">{{ getLossDescription(firstReport) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">路产损失:</span>
|
|
||||||
<span class="info-value">{{ firstReport.totalLossAmount ? firstReport.totalLossAmount + '万元' : '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">有无车辆滞留:</span>
|
|
||||||
<span class="info-value">{{ getVehicleStrandedText(firstReport) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">滞留车辆:</span>
|
|
||||||
<span class="info-value">{{ firstReport.strandedVehicleCount || 0 }}辆</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">预计恢复时间:</span>
|
|
||||||
<span class="info-value">{{ firstReport.expectRecoverTime || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">实际恢复时间:</span>
|
|
||||||
<span class="info-value">{{ firstReport.actualRecoverTime || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-row">
|
|
||||||
<span class="info-label">现场描述:</span>
|
|
||||||
<span class="info-value">{{ firstReport.siteDescription || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<!-- 附件 -->
|
|
||||||
<div class="info-row" v-if="firstReport.fileList && firstReport.fileList.length > 0">
|
|
||||||
<span class="info-label">附件:</span>
|
|
||||||
<div class="attachment-list">
|
|
||||||
<div v-for="(file, index) in firstReport.fileList" :key="index" class="attachment-item">
|
|
||||||
<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(file)">预览</van-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 续报列表 -->
|
|
||||||
<div v-for="(report, index) in continueReports" :key="index" class="report-section">
|
|
||||||
<div class="report-header">
|
|
||||||
<span class="report-title">续报{{ index + 1 }}</span>
|
|
||||||
<span class="report-meta">{{ report.reporterName || '-' }} {{ report.reportTime || '-' }}</span>
|
<span class="report-meta">{{ report.reporterName || '-' }} {{ report.reportTime || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="report-content">
|
<div class="report-content">
|
||||||
@ -270,8 +215,8 @@
|
|||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
<!-- 底部按钮:未解除状态显示续报按钮 -->
|
<!-- 底部按钮:未解除状态显示续报按钮 -->
|
||||||
<div class="footer-buttons" v-if="!isEventResolved">
|
<div class="footer-buttons">
|
||||||
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
|
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
|
||||||
</div>
|
</div>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
@ -292,8 +237,7 @@ const route = useRoute()
|
|||||||
// 详情数据(对应 Data 接口)
|
// 详情数据(对应 Data 接口)
|
||||||
const detailData = ref({
|
const detailData = ref({
|
||||||
event: null, // Event 对象
|
event: null, // Event 对象
|
||||||
report: null, // Report 对象(首报)
|
reportList: [], // 填报列表(包含首报和续报)
|
||||||
reportList: [], // 续报列表(可选,如果接口返回)
|
|
||||||
fileList: [], // 附件列表
|
fileList: [], // 附件列表
|
||||||
lossList: [], // 损失列表
|
lossList: [], // 损失列表
|
||||||
occurLocation: '',
|
occurLocation: '',
|
||||||
@ -302,42 +246,28 @@ const detailData = ref({
|
|||||||
routeNo: ''
|
routeNo: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
// 首报(优先使用 report,如果没有则从 reportList 中找 reportType === 1)
|
const allReports = computed(() => {
|
||||||
const firstReport = computed(() => {
|
const reports = detailData.value.reportList?.map((item, index)=>{
|
||||||
if (detailData.value.report) {
|
item.title = index == 0 ? '首报' : ('续报' + index)
|
||||||
return detailData.value.report
|
return item
|
||||||
}
|
}) || []
|
||||||
return detailData.value.reportList?.find(r => r.reportType === 1)
|
return reports.reverse()
|
||||||
})
|
|
||||||
|
|
||||||
// 续报列表(reportType === 2)
|
|
||||||
const continueReports = computed(() => {
|
|
||||||
return detailData.value.reportList?.filter(r => r.reportType === 2) || []
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 是否有填报数据
|
// 是否有填报数据
|
||||||
const hasReportData = computed(() => {
|
const hasReportData = computed(() => {
|
||||||
return firstReport.value || continueReports.value.length > 0
|
return allReports.value.length > 0
|
||||||
})
|
})
|
||||||
|
|
||||||
// 判断事件是否已解除(根据实际恢复时间或续报状态判断)
|
|
||||||
const isEventResolved = computed(() => {
|
|
||||||
// 如果首报有实际恢复时间且不为空,则认为已解除
|
|
||||||
// if (firstReport.value?.actualRecoverTime) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// // 检查续报中是否有实际恢复时间
|
|
||||||
// return continueReports.value.some(r => r.actualRecoverTime)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取事件状态文本
|
// 获取事件状态文本
|
||||||
const getEventStatusText = () => {
|
const getEventStatusText = () => {
|
||||||
return isEventResolved.value ? '已解除' : '未解除'
|
return detailData.eventStatus === 1 ? '已解除' : '未解除'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取事件状态类型
|
// 获取事件状态类型
|
||||||
const getEventStatusType = () => {
|
const getEventStatusType = () => {
|
||||||
return isEventResolved.value ? 'success' : 'danger'
|
return detailData.eventStatus === 1 ? 'success' : 'danger'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 格式化处置措施(逗号分隔转中文)
|
// 格式化处置措施(逗号分隔转中文)
|
||||||
@ -396,8 +326,7 @@ const getDisasterDetail = async () => {
|
|||||||
const data = result.data
|
const data = result.data
|
||||||
detailData.value = {
|
detailData.value = {
|
||||||
event: data.event || null,
|
event: data.event || null,
|
||||||
report: data.report || null,
|
reportList: data.report || [], // 直接使用 reportList,包含首报和续报
|
||||||
reportList: data.reportList || [],
|
|
||||||
fileList: data.fileList || [],
|
fileList: data.fileList || [],
|
||||||
lossList: data.lossList || [],
|
lossList: data.lossList || [],
|
||||||
occurLocation: data.occurLocation || '',
|
occurLocation: data.occurLocation || '',
|
||||||
|
|||||||
@ -58,7 +58,7 @@
|
|||||||
<span>校准经纬度</span>
|
<span>校准经纬度</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 路况位置 (event.endStakeNo) -->
|
<!-- 路况位置 (occurLocation) -->
|
||||||
<van-field v-model="formData.occurLocation" label="路况位置" placeholder="请填写" />
|
<van-field v-model="formData.occurLocation" label="路况位置" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 阻断点小地名 (event.blockedPointName) -->
|
<!-- 阻断点小地名 (event.blockedPointName) -->
|
||||||
@ -71,12 +71,13 @@
|
|||||||
<div class="disposal-measures">
|
<div class="disposal-measures">
|
||||||
<span class="measures-label">处置措施</span>
|
<span class="measures-label">处置措施</span>
|
||||||
<div class="measures-options">
|
<div class="measures-options">
|
||||||
<van-checkbox-group v-model="disposalMeasuresArray" direction="horizontal">
|
<!-- 改为单选,使用 van-radio-group -->
|
||||||
<van-checkbox name="halfClose">半幅封闭</van-checkbox>
|
<van-radio-group v-model="disposalMeasureValue" direction="horizontal">
|
||||||
<van-checkbox name="fullClose">全副封闭</van-checkbox>
|
<van-radio name="halfClose">半幅封闭</van-radio>
|
||||||
<van-checkbox name="bypass">便道通行</van-checkbox>
|
<van-radio name="fullClose">全副封闭</van-radio>
|
||||||
<van-checkbox name="normal">正常通行</van-checkbox>
|
<van-radio name="bypass">便道通行</van-radio>
|
||||||
</van-checkbox-group>
|
<van-radio name="normal">正常通行</van-radio>
|
||||||
|
</van-radio-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -198,8 +199,8 @@ const route = useRoute()
|
|||||||
// 是否为续报
|
// 是否为续报
|
||||||
const isContinue = computed(() => route.query.isContinue)
|
const isContinue = computed(() => route.query.isContinue)
|
||||||
|
|
||||||
// 处置措施数组(用于多选框组,需要转换为逗号分隔的字符串)
|
// 处置措施单选值(用于单选组件)
|
||||||
const disposalMeasuresArray = ref([])
|
const disposalMeasureValue = ref('')
|
||||||
|
|
||||||
// 附件列表
|
// 附件列表
|
||||||
const imageFileList = ref([])
|
const imageFileList = ref([])
|
||||||
@ -240,7 +241,7 @@ const formData = reactive({
|
|||||||
actualRecoverTime: '', // 实际恢复时间
|
actualRecoverTime: '', // 实际恢复时间
|
||||||
damagedVehicleCount: '', // 损坏车辆
|
damagedVehicleCount: '', // 损坏车辆
|
||||||
deadCount: '', // 死亡人员
|
deadCount: '', // 死亡人员
|
||||||
disposalMeasures: '', // 处置措施(逗号分隔)
|
disposalMeasures: '', // 处置措施(单个值,不再用逗号分隔)
|
||||||
expectRecoverTime: '', // 预计恢复时间
|
expectRecoverTime: '', // 预计恢复时间
|
||||||
injuredCount: '', // 受伤人员
|
injuredCount: '', // 受伤人员
|
||||||
investedFunds: '', // 已投资金
|
investedFunds: '', // 已投资金
|
||||||
@ -260,14 +261,10 @@ const formData = reactive({
|
|||||||
fileList: []
|
fileList: []
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听处置措施数组变化,转换为逗号分隔的字符串存到 report.disposalMeasures
|
// 监听处置措施单选值变化,直接赋值给 report.disposalMeasures
|
||||||
watch(
|
watch(disposalMeasureValue, (newVal) => {
|
||||||
disposalMeasuresArray,
|
formData.report.disposalMeasures = newVal
|
||||||
(newVal) => {
|
})
|
||||||
formData.report.disposalMeasures = newVal.join(',')
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
)
|
|
||||||
|
|
||||||
// 监听附件变化,同步到 fileList
|
// 监听附件变化,同步到 fileList
|
||||||
watch(
|
watch(
|
||||||
@ -313,12 +310,12 @@ watch(
|
|||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
// 从 report.disposalMeasures 初始化处置措施数组
|
// 从 report.disposalMeasures 初始化处置措施单选值
|
||||||
watch(
|
watch(
|
||||||
() => formData.report.disposalMeasures,
|
() => formData.report.disposalMeasures,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
if (newVal && typeof newVal === 'string') {
|
if (newVal && typeof newVal === 'string') {
|
||||||
disposalMeasuresArray.value = newVal.split(',').filter(Boolean)
|
disposalMeasureValue.value = newVal
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
@ -368,9 +365,9 @@ const initFormData = (newVal) => {
|
|||||||
fileList: newVal.fileList || []
|
fileList: newVal.fileList || []
|
||||||
})
|
})
|
||||||
|
|
||||||
// 初始化处置措施数组
|
// 初始化处置措施单选值(直接赋值,不再需要 split)
|
||||||
if (newVal.report?.disposalMeasures) {
|
if (newVal.report?.disposalMeasures) {
|
||||||
disposalMeasuresArray.value = newVal.report.disposalMeasures.split(',').filter(Boolean)
|
disposalMeasureValue.value = newVal.report.disposalMeasures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,12 +477,12 @@ defineExpose({
|
|||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
.measures-options {
|
.measures-options {
|
||||||
:deep(.van-checkbox-group) {
|
:deep(.van-radio-group) {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
}
|
}
|
||||||
:deep(.van-checkbox) {
|
:deep(.van-radio) {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,4 +523,4 @@ defineExpose({
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
BIN
packages/screen/src/assets/MaMap_img/线路icon定位@2x.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
@ -163,7 +163,16 @@ const routes = [
|
|||||||
name: 'DisasterReport',
|
name: 'DisasterReport',
|
||||||
component: () => import('../views/DisasterManagement/DisasterReport/DisasterReport.vue'),
|
component: () => import('../views/DisasterManagement/DisasterReport/DisasterReport.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '水毁事件填报',
|
title: '灾毁事件填报',
|
||||||
|
breadcrumb: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/waterDisasterDetail',
|
||||||
|
name: 'WaterDisasterDetail',
|
||||||
|
component: () => import('../views/DisasterManagement/DisasterDetail/WaterDisasterDetail.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '水毁事件详情',
|
||||||
breadcrumb: true
|
breadcrumb: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,475 @@
|
|||||||
|
<template>
|
||||||
|
<div class="water-disaster-pc">
|
||||||
|
<!-- 合并后的单个卡片 -->
|
||||||
|
<el-card class="form-card" shadow="never">
|
||||||
|
<div slot="header" class="card-header">
|
||||||
|
<span>续保信息</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 所有表单项合并到一个区域,每行一个 -->
|
||||||
|
<el-form :model="formData" label-width="120px" size="small">
|
||||||
|
<!-- 处置措施 -->
|
||||||
|
<el-form-item label="处置措施">
|
||||||
|
<el-radio-group v-model="disposalMeasureValue">
|
||||||
|
<el-radio label="halfClose">半幅封闭</el-radio>
|
||||||
|
<el-radio label="fullClose">全副封闭</el-radio>
|
||||||
|
<el-radio label="bypass">便道通行</el-radio>
|
||||||
|
<el-radio label="normal">正常通行</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 预计恢复时间 -->
|
||||||
|
<el-form-item label="预计恢复时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.report.expectRecoverTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="请选择时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm"
|
||||||
|
:picker-options="pickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 实际恢复时间 -->
|
||||||
|
<el-form-item label="实际恢复时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.report.actualRecoverTime"
|
||||||
|
type="datetime"
|
||||||
|
placeholder="请选择时间"
|
||||||
|
value-format="yyyy-MM-dd HH:mm"
|
||||||
|
:picker-options="pickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 受伤人员 -->
|
||||||
|
<el-form-item label="受伤人员">
|
||||||
|
<el-input-number v-model="formData.report.injuredCount" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">人</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 死亡人员 -->
|
||||||
|
<el-form-item label="死亡人员">
|
||||||
|
<el-input-number v-model="formData.report.deadCount" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">人</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 滞留人员 -->
|
||||||
|
<el-form-item label="滞留人员">
|
||||||
|
<el-input-number v-model="formData.report.strandedPersonCount" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">人</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 损坏车辆 -->
|
||||||
|
<el-form-item label="损坏车辆">
|
||||||
|
<el-input-number v-model="formData.report.damagedVehicleCount" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">辆</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 滞留车辆 -->
|
||||||
|
<el-form-item label="滞留车辆">
|
||||||
|
<el-input-number v-model="formData.report.strandedVehicleCount" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">辆</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 损失列表组件 -->
|
||||||
|
<el-form-item label="灾毁损失">
|
||||||
|
<loss-list v-model="formData.lossList" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 处理情况 -->
|
||||||
|
<el-form-item label="处理情况">
|
||||||
|
<el-input v-model="formData.report.remark" type="textarea" :rows="2" placeholder="请填写(选填)" style="width: 60%" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 损失总金额 -->
|
||||||
|
<el-form-item label="损失总金额">
|
||||||
|
<el-input v-model="formData.report.totalLossAmount" placeholder="请填写(选填)" style="width: 300px">
|
||||||
|
<template slot="append">万元</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 已投机械 -->
|
||||||
|
<el-form-item label="已投机械">
|
||||||
|
<el-input v-model="formData.report.investedMachinery" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">台/班</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 已投入力 -->
|
||||||
|
<el-form-item label="已投入力">
|
||||||
|
<el-input-number v-model="formData.report.investedManpower" :min="0" :controls="false" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">人次</template>
|
||||||
|
</el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 已投资金 -->
|
||||||
|
<el-form-item label="已投资金">
|
||||||
|
<el-input v-model="formData.report.investedFunds" placeholder="请填写" style="width: 300px">
|
||||||
|
<template slot="append">万元</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 现场描述 -->
|
||||||
|
<el-form-item label="现场描述">
|
||||||
|
<el-input v-model="formData.report.siteDescription" type="textarea" :rows="2" placeholder="请填写" style="width: 60%" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 是否需要恢复重建 -->
|
||||||
|
<el-form-item label="是否需要恢复重建">
|
||||||
|
<el-radio-group v-model="formData.event.needsRecovery">
|
||||||
|
<el-radio :label="true">是</el-radio>
|
||||||
|
<el-radio :label="false">否</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleSubmit">追加记录</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, watch, computed } from 'vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { request } from '@shared/utils/request'
|
||||||
|
// import LossList from './LossList.vue'
|
||||||
|
|
||||||
|
// Props 定义
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Emits 定义
|
||||||
|
const emit = defineEmits(['input', 'change', 'submit'])
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formData = reactive({
|
||||||
|
occurLocation: '',
|
||||||
|
occurTime: '',
|
||||||
|
roadConditionType: '',
|
||||||
|
routeNo: '',
|
||||||
|
event: {
|
||||||
|
blockedMileage: '',
|
||||||
|
blockedPointName: '',
|
||||||
|
contactPerson: '',
|
||||||
|
contactPhone: '',
|
||||||
|
damageCount: '',
|
||||||
|
district: '',
|
||||||
|
endStakeLat: '',
|
||||||
|
endStakeLng: '',
|
||||||
|
endStakeNo: '',
|
||||||
|
estimatedRecoveryCost: '',
|
||||||
|
inspectionMileage: '',
|
||||||
|
isBlocked: '',
|
||||||
|
needsRecovery: '',
|
||||||
|
repairProgress: '',
|
||||||
|
reporterUnit: '',
|
||||||
|
startStakeLat: '',
|
||||||
|
startStakeLng: '',
|
||||||
|
startStakeNo: ''
|
||||||
|
},
|
||||||
|
report: {
|
||||||
|
actualRecoverTime: '',
|
||||||
|
damagedVehicleCount: '',
|
||||||
|
deadCount: '',
|
||||||
|
disposalMeasures: '',
|
||||||
|
expectRecoverTime: '',
|
||||||
|
injuredCount: '',
|
||||||
|
investedFunds: '',
|
||||||
|
investedMachinery: '',
|
||||||
|
investedManpower: '',
|
||||||
|
remark: '',
|
||||||
|
siteDescription: '',
|
||||||
|
strandedPersonCount: '',
|
||||||
|
strandedVehicleCount: '',
|
||||||
|
totalLossAmount: ''
|
||||||
|
},
|
||||||
|
lossList: [],
|
||||||
|
fileList: []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 处置措施单选值
|
||||||
|
const disposalMeasureValue = ref('')
|
||||||
|
|
||||||
|
// 下拉选项
|
||||||
|
const roadConditionOptions = [
|
||||||
|
{ label: '高速公路', value: '高速公路' },
|
||||||
|
{ label: '国道', value: '国道' },
|
||||||
|
{ label: '省道', value: '省道' },
|
||||||
|
{ label: '县道', value: '县道' },
|
||||||
|
{ label: '乡道', value: '乡道' },
|
||||||
|
{ label: '村道', value: '村道' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const blockedOptions = [
|
||||||
|
{ label: '是', value: true },
|
||||||
|
{ label: '否', value: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
const repairProgressOptions = [
|
||||||
|
{ label: '未抢修', value: '未抢修' },
|
||||||
|
{ label: '抢修中', value: '抢修中' },
|
||||||
|
{ label: '已完成', value: '已完成' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// 日期选择器配置
|
||||||
|
const pickerOptions = {
|
||||||
|
disabledDate(time) {
|
||||||
|
return time.getTime() < new Date(2020, 0, 1) || time.getTime() > new Date(2030, 11, 31)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听处置措施单选值变化
|
||||||
|
watch(disposalMeasureValue, (newVal) => {
|
||||||
|
formData.report.disposalMeasures = newVal
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听外部传入的值
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal && Object.keys(newVal).length > 0) {
|
||||||
|
initFormData(newVal)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 监听表单数据变化,向外传递
|
||||||
|
watch(
|
||||||
|
() => formData,
|
||||||
|
(newVal) => {
|
||||||
|
emit('input', newVal)
|
||||||
|
emit('change', newVal)
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 从 report.disposalMeasures 初始化处置措施单选值
|
||||||
|
watch(
|
||||||
|
() => formData.report.disposalMeasures,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal && typeof newVal === 'string') {
|
||||||
|
disposalMeasureValue.value = newVal
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
// 初始化表单数据
|
||||||
|
const initFormData = (data) => {
|
||||||
|
Object.assign(formData, {
|
||||||
|
occurLocation: data.occurLocation || '',
|
||||||
|
occurTime: data.occurTime || '',
|
||||||
|
roadConditionType: data.roadConditionType || '',
|
||||||
|
routeNo: data.routeNo || '',
|
||||||
|
event: { ...formData.event, ...(data.event || {}) },
|
||||||
|
report: { ...formData.report, ...(data.report || {}) },
|
||||||
|
lossList: data.lossList || [],
|
||||||
|
fileList: data.fileList || []
|
||||||
|
})
|
||||||
|
|
||||||
|
if (data.report?.disposalMeasures) {
|
||||||
|
disposalMeasureValue.value = data.report.disposalMeasures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校准时间
|
||||||
|
const calibrateTime = () => {
|
||||||
|
const now = new Date()
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(now.getDate()).padStart(2, '0')
|
||||||
|
const hours = String(now.getHours()).padStart(2, '0')
|
||||||
|
const minutes = String(now.getMinutes()).padStart(2, '0')
|
||||||
|
formData.occurTime = `${year}-${month}-${day} ${hours}:${minutes}`
|
||||||
|
ElMessage.success('时间已校准为当前时间')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校准起点经纬度
|
||||||
|
const calibrateStartCoord = () => {
|
||||||
|
formData.event.startStakeLng = '108.41763025'
|
||||||
|
formData.event.startStakeLat = '108.41763025'
|
||||||
|
ElMessage.success('起点经纬度已校准')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 校准止点经纬度
|
||||||
|
const calibrateEndCoord = () => {
|
||||||
|
formData.event.endStakeLng = '108.41763025'
|
||||||
|
formData.event.endStakeLat = '108.41763025'
|
||||||
|
ElMessage.success('止点经纬度已校准')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单验证
|
||||||
|
const validate = () => {
|
||||||
|
if (!formData.occurTime) {
|
||||||
|
ElMessage.warning('请填写发生时间')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!formData.routeNo) {
|
||||||
|
ElMessage.warning('请填写线路编号')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取表单数据
|
||||||
|
const getFormData = () => {
|
||||||
|
return { ...formData }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置表单
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(formData, {
|
||||||
|
occurLocation: '',
|
||||||
|
occurTime: '',
|
||||||
|
roadConditionType: '',
|
||||||
|
routeNo: '',
|
||||||
|
event: {
|
||||||
|
blockedMileage: '',
|
||||||
|
blockedPointName: '',
|
||||||
|
contactPerson: '',
|
||||||
|
contactPhone: '',
|
||||||
|
damageCount: '',
|
||||||
|
district: '',
|
||||||
|
endStakeLat: '',
|
||||||
|
endStakeLng: '',
|
||||||
|
endStakeNo: '',
|
||||||
|
estimatedRecoveryCost: '',
|
||||||
|
inspectionMileage: '',
|
||||||
|
isBlocked: '',
|
||||||
|
needsRecovery: '',
|
||||||
|
repairProgress: '',
|
||||||
|
reporterUnit: '',
|
||||||
|
startStakeLat: '',
|
||||||
|
startStakeLng: '',
|
||||||
|
startStakeNo: ''
|
||||||
|
},
|
||||||
|
report: {
|
||||||
|
actualRecoverTime: '',
|
||||||
|
damagedVehicleCount: '',
|
||||||
|
deadCount: '',
|
||||||
|
disposalMeasures: '',
|
||||||
|
expectRecoverTime: '',
|
||||||
|
injuredCount: '',
|
||||||
|
investedFunds: '',
|
||||||
|
investedMachinery: '',
|
||||||
|
investedManpower: '',
|
||||||
|
remark: '',
|
||||||
|
siteDescription: '',
|
||||||
|
strandedPersonCount: '',
|
||||||
|
strandedVehicleCount: '',
|
||||||
|
totalLossAmount: ''
|
||||||
|
},
|
||||||
|
lossList: [],
|
||||||
|
fileList: []
|
||||||
|
})
|
||||||
|
disposalMeasureValue.value = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交方法
|
||||||
|
const submit = () => {
|
||||||
|
if (validate()) {
|
||||||
|
emit('submit', getFormData())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
// 验证表单
|
||||||
|
if (!validate()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取表单数据
|
||||||
|
|
||||||
|
// 添加事件类型和站点信息
|
||||||
|
const submitData = {
|
||||||
|
...formData
|
||||||
|
// 可以在这里添加站点信息等其他数据
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await request({
|
||||||
|
url: '/snow-ops-platform/water-damage/addOrUpdate',
|
||||||
|
method: 'post',
|
||||||
|
data: submitData
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.code === '00000') {
|
||||||
|
ElMessage.success('提交成功')
|
||||||
|
|
||||||
|
emit("refresh")
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.message)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('提交失败,请重试')
|
||||||
|
console.error('提交失败:', error)
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 暴露方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
validate,
|
||||||
|
initFormData,
|
||||||
|
getFormData,
|
||||||
|
resetForm,
|
||||||
|
calibrateTime,
|
||||||
|
calibrateStartCoord,
|
||||||
|
calibrateEndCoord
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.water-disaster-pc {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.form-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
border-left: 4px solid #409eff;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-form-item {
|
||||||
|
margin-bottom: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input-group__append {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input-number {
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
.el-input-group__append {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-radio-group {
|
||||||
|
.el-radio {
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,618 @@
|
|||||||
|
<template>
|
||||||
|
<div class="web-detail-container">
|
||||||
|
<!-- 页面头部 -->
|
||||||
|
<div class="page-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<el-button :icon="ArrowLeft" @click="handleClickBack">返回</el-button>
|
||||||
|
<h2 class="page-title">灾毁详情</h2>
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<el-tag :type="getEventStatusType()" size="large">
|
||||||
|
{{ getEventStatusText() }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-container">
|
||||||
|
<div class="left-panel">
|
||||||
|
<!-- 基本信息卡片 -->
|
||||||
|
<el-card class="info-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-title">基本信息</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">事件类型:</span>
|
||||||
|
<span class="info-value">水毁事件</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">路况类别:</span>
|
||||||
|
<span class="info-value">{{ detailData.roadConditionType || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">是否阻断:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.isBlocked ? '是' : '否' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">抢修进度:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.repairProgress || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">水毁处数:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.damageCount || 0 }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">阻断里程:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.blockedMileage ? detailData.event.blockedMileage + '公里' : '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">发生时间:</span>
|
||||||
|
<span class="info-value">{{ detailData.occurTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">线路编号:</span>
|
||||||
|
<span class="info-value">{{ detailData.routeNo || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">地点路线:</span>
|
||||||
|
<span class="info-value">{{ detailData.occurLocation || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">起点桩号:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.startStakeNo || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">起点桩经度:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.startStakeLng || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">起点桩纬度:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.startStakeLat || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">止点桩号:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.endStakeNo || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">止点桩经度:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.endStakeLng || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">止点桩纬度:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.endStakeLat || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">路况位置:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.blockedPointName || detailData.occurLocation || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">阻断点小地名:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.blockedPointName || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">上报区县:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.district || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">巡查里程:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.inspectionMileage ? detailData.event.inspectionMileage + '公里' : '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">是否恢复重建:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.needsRecovery ? '是' : '否' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">恢复重建预估费用:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.estimatedRecoveryCost ? detailData.event.estimatedRecoveryCost + '万元' : '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row :gutter="20" class="info-row">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">联系人:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.contactPerson || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">联系电话:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.contactPhone || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="8">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">填报单位:</span>
|
||||||
|
<span class="info-value">{{ detailData.event?.reporterUnit || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 填报信息卡片 -->
|
||||||
|
<el-card class="info-card" shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-title">填报信息</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<div v-if="hasReportData">
|
||||||
|
<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="info-list">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">处置情况:</span>
|
||||||
|
<span class="info-value">{{ formatDisposalMeasures(report.disposalMeasures) || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">塌方及损失:</span>
|
||||||
|
<span class="info-value">{{ getLossDescription(report) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">路产损失:</span>
|
||||||
|
<span class="info-value">{{ report.totalLossAmount ? report.totalLossAmount + '万元' : '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">有无车辆滞留:</span>
|
||||||
|
<span class="info-value">{{ getVehicleStrandedText(report) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">滞留车辆:</span>
|
||||||
|
<span class="info-value">{{ report.strandedVehicleCount || 0 }}辆</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">预计恢复时间:</span>
|
||||||
|
<span class="info-value">{{ report.expectRecoverTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">实际恢复时间:</span>
|
||||||
|
<span class="info-value">{{ report.actualRecoverTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="info-label">现场描述:</span>
|
||||||
|
<span class="info-value">{{ report.siteDescription || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 附件 -->
|
||||||
|
<div v-if="report.fileList && report.fileList.length > 0" class="info-item attachment-item">
|
||||||
|
<span class="info-label">附件:</span>
|
||||||
|
<div class="attachment-list">
|
||||||
|
<el-link v-for="(file, fileIndex) in report.fileList" :key="fileIndex" :underline="false" @click="previewFile(file)" class="attachment-link">
|
||||||
|
<el-icon><Picture v-if="file.fileType === 1" /><VideoCamera v-else /></el-icon>
|
||||||
|
<span class="file-name">{{ file.fileName }}</span>
|
||||||
|
</el-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-empty v-else description="暂无填报信息" :image-size="100" />
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 底部按钮 -->
|
||||||
|
<!-- <div class="footer-buttons">
|
||||||
|
<el-button type="primary" size="large" @click="handleContinueReport" class="footer-btn"> 续报 </el-button>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
<div class="right-panel" v-if="isEdit">
|
||||||
|
<ContinueReport ref="continueReport" @refresh="getDisasterDetail" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, computed } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { ArrowLeft, Picture, VideoCamera } from '@element-plus/icons-vue'
|
||||||
|
import ContinueReport from './ContinueReport.vue'
|
||||||
|
import { request } from '@shared/utils/request'
|
||||||
|
import mockData from '../DisasterReport/waterMockJson.json'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// 详情数据
|
||||||
|
const detailData = ref({
|
||||||
|
event: null,
|
||||||
|
report: [],
|
||||||
|
fileList: [],
|
||||||
|
lossList: [],
|
||||||
|
occurLocation: '',
|
||||||
|
occurTime: '',
|
||||||
|
roadConditionType: '',
|
||||||
|
routeNo: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 事件状态
|
||||||
|
const eventStatus = ref(0)
|
||||||
|
|
||||||
|
// 是否为编辑
|
||||||
|
const isEdit = computed(() => {
|
||||||
|
return route.query.mode === 'edit'
|
||||||
|
})
|
||||||
|
|
||||||
|
const continueReport = ref(null)
|
||||||
|
|
||||||
|
// 所有填报记录(首报 + 续报)
|
||||||
|
const allReports = computed(() => {
|
||||||
|
const reports =
|
||||||
|
detailData.value.report?.map((item, index) => {
|
||||||
|
item.title = index === 0 ? '首报' : '续报' + index
|
||||||
|
return item
|
||||||
|
}) || []
|
||||||
|
return reports.reverse()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 是否有填报数据
|
||||||
|
const hasReportData = computed(() => {
|
||||||
|
return allReports.value.length > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取事件状态文本
|
||||||
|
const getEventStatusText = () => {
|
||||||
|
return eventStatus.value === 1 ? '已解除' : '未解除'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取事件状态类型
|
||||||
|
const getEventStatusType = () => {
|
||||||
|
return eventStatus.value === 1 ? 'success' : 'danger'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化处置措施
|
||||||
|
const formatDisposalMeasures = (measures) => {
|
||||||
|
if (!measures) return ''
|
||||||
|
const measureMap = {
|
||||||
|
halfClose: '半幅封闭',
|
||||||
|
fullClose: '全副封闭',
|
||||||
|
bypass: '便道通行',
|
||||||
|
normal: '正常通行'
|
||||||
|
}
|
||||||
|
return measures
|
||||||
|
.split(',')
|
||||||
|
.map((m) => measureMap[m.trim()] || m.trim())
|
||||||
|
.join('、')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取损失描述
|
||||||
|
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 ? `有车滞留,共${count}辆` : '无车滞留'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取灾毁详情
|
||||||
|
const getDisasterDetail = async () => {
|
||||||
|
const id = route.query.id
|
||||||
|
if (!id) {
|
||||||
|
ElMessage.warning('缺少灾毁ID')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await request({
|
||||||
|
url: `/snow-ops-platform/water-damage/getById`,
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result?.data) {
|
||||||
|
const data = result.data
|
||||||
|
detailData.value = {
|
||||||
|
event: data.event || null,
|
||||||
|
report: data.report || [],
|
||||||
|
fileList: data.fileList || [],
|
||||||
|
lossList: data.lossList || [],
|
||||||
|
occurLocation: data.occurLocation || '',
|
||||||
|
occurTime: data.occurTime || '',
|
||||||
|
roadConditionType: data.roadConditionType || '',
|
||||||
|
routeNo: data.routeNo || ''
|
||||||
|
}
|
||||||
|
eventStatus.value = data.eventStatus || 0
|
||||||
|
|
||||||
|
if (isEdit.value) {
|
||||||
|
const newFormData = {
|
||||||
|
...data,
|
||||||
|
lossList: null,
|
||||||
|
report: mockData.report,
|
||||||
|
fileList: null
|
||||||
|
}
|
||||||
|
continueReport.value?.initFormData(newFormData)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(result.message || '获取详情失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取灾毁详情失败:', error)
|
||||||
|
ElMessage.error('获取详情失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击返回
|
||||||
|
const handleClickBack = () => {
|
||||||
|
router.push('/disasterManagement')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 续报
|
||||||
|
const handleContinueReport = () => {
|
||||||
|
router.push({
|
||||||
|
path: '/disasterReport',
|
||||||
|
query: {
|
||||||
|
id: route.query.id,
|
||||||
|
eventId: detailData.value.event?.id,
|
||||||
|
isContinue: 'true'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览附件
|
||||||
|
const previewFile = (file) => {
|
||||||
|
if (file.fileUrl) {
|
||||||
|
window.open(file.fileUrl, '_blank')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDisasterDetail()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.web-detail-container {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
:deep(.el-card__header) {
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
.card-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
width: 120px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
flex: 1;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-section {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: baseline;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px dashed #dcdfe6;
|
||||||
|
|
||||||
|
.report-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-meta {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-wrapper {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 8px;
|
||||||
|
border-top: 1px dashed #ebeef5;
|
||||||
|
|
||||||
|
.attachment-item {
|
||||||
|
.attachment-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.attachment-link {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #ecf5ff;
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-name {
|
||||||
|
font-size: 13px;
|
||||||
|
max-width: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-buttons {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 16px 24px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.08);
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
.footer-btn {
|
||||||
|
width: 200px;
|
||||||
|
height: 44px;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 22px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-container {
|
||||||
|
display: flex;
|
||||||
|
.left-panel {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.right-panel {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -298,12 +298,12 @@ const resetFilters = () => {
|
|||||||
|
|
||||||
// 查看详情
|
// 查看详情
|
||||||
const handleDetail = (row) => {
|
const handleDetail = (row) => {
|
||||||
router.push({ path: '/disasterDetail', query: { id: row.id } })
|
router.push({ path: '/waterDisasterDetail', query: { id: row.id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑
|
// 编辑
|
||||||
const handleEdit = (row) => {
|
const handleEdit = (row) => {
|
||||||
router.push({ path: '/disasterReport', query: { id: row.id, mode: 'edit' } })
|
router.push({ path: '/waterDisasterDetail', query: { id: row.id, mode: 'edit' } })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增跳转
|
// 新增跳转
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"occurLocation": "G108国道 K2250+300处",
|
||||||
|
"occurTime": "2024-07-15 14:30:00",
|
||||||
|
"roadConditionType": "国道",
|
||||||
|
"routeNo": "G108",
|
||||||
|
"event": {
|
||||||
|
"blockedMileage": 1.5,
|
||||||
|
"blockedPointName": "磨盘山隧道口",
|
||||||
|
"contactPerson": "张明",
|
||||||
|
"contactPhone": "13812345678",
|
||||||
|
"damageCount": 3,
|
||||||
|
"district": "武侯区",
|
||||||
|
"endStakeLat": "30.658712",
|
||||||
|
"endStakeLng": "104.082356",
|
||||||
|
"endStakeNo": "K2251+200",
|
||||||
|
"estimatedRecoveryCost": 120.5,
|
||||||
|
"inspectionMileage": 25.6,
|
||||||
|
"isBlocked": true,
|
||||||
|
"needsRecovery": true,
|
||||||
|
"repairProgress": "抢修中",
|
||||||
|
"reporterUnit": "武侯区交通运输局",
|
||||||
|
"startStakeLat": "30.652145",
|
||||||
|
"startStakeLng": "104.075632",
|
||||||
|
"startStakeNo": "K2250+300"
|
||||||
|
},
|
||||||
|
"report": {
|
||||||
|
"damagedVehicleCount": 2,
|
||||||
|
"strandedPersonCount": 12,
|
||||||
|
"deadCount": 0,
|
||||||
|
"strandedVehicleCount": 12,
|
||||||
|
"disposalMeasures": "halfClose,bypass",
|
||||||
|
"actualRecoverTime": "2024-07-17 12:00:00",
|
||||||
|
"expectRecoverTime": "2024-07-18 18:00:00",
|
||||||
|
"injuredCount": 1,
|
||||||
|
"investedFunds": 35.8,
|
||||||
|
"investedMachinery": 6,
|
||||||
|
"investedManpower": 45,
|
||||||
|
"remark": "已组织抢险队伍进行抢通,便道已修建完成",
|
||||||
|
"siteDescription": "因持续强降雨导致山体滑坡,掩埋路面约50米,边坡垮塌严重",
|
||||||
|
"totalLossAmount": 85.6
|
||||||
|
},
|
||||||
|
"lossList": [
|
||||||
|
],
|
||||||
|
"fileList": []
|
||||||
|
}
|
||||||
156
packages/screen/src/views/RiskWarning/Dialog/mapInfoDialog.vue
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<base-dialog
|
||||||
|
v-model:visible="props.visible"
|
||||||
|
:title="dialogTitle"
|
||||||
|
:table-data="[]"
|
||||||
|
:table-columns="[]"
|
||||||
|
:table-height="0"
|
||||||
|
:total="0"
|
||||||
|
:current-page="1"
|
||||||
|
:page-size="10"
|
||||||
|
:z-index="1000"
|
||||||
|
:max-width="400"
|
||||||
|
:show-filter="false"
|
||||||
|
:show-pagination="false"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 标题栏下方自定义插槽 -->
|
||||||
|
<template #header>
|
||||||
|
<div class="dialog-content">
|
||||||
|
<div class="info-item" v-for="(item, index) in dialogItems" :key="index">
|
||||||
|
<label class="info-label">{{ item.label }}:</label>
|
||||||
|
<span class="info-value">{{ item.value }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</base-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, defineEmits, computed } from "vue";
|
||||||
|
import baseDialog from "../component/baseDialog.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "project", // project, tunnel, bridge, road
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:visible"]);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据类型和数据显示不同的标题和内容
|
||||||
|
const dialogTitle = computed(() => {
|
||||||
|
const titleMap = {
|
||||||
|
project: "项目信息",
|
||||||
|
tunnel: "隧道信息",
|
||||||
|
bridge: "桥梁信息",
|
||||||
|
road: "路段信息",
|
||||||
|
};
|
||||||
|
return titleMap[props.type] || "详细信息";
|
||||||
|
});
|
||||||
|
|
||||||
|
const dialogItems = computed(() => {
|
||||||
|
const data = props.data;
|
||||||
|
const type = props.type;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "project":
|
||||||
|
return [
|
||||||
|
{ label: "项目名称", value: data.NAME || data.name || "-" },
|
||||||
|
{ label: "所属区县", value: data.COUNTY || data.county || "-" },
|
||||||
|
{ label: "路线编号", value: data.ROUTE_CODE || data.routeCode || "-" },
|
||||||
|
{ label: "路线名称", value: data.ROUTE_NAME || data.routeName || "-" },
|
||||||
|
{ label: "项目类型", value: data.TYPE || data.type || "-" },
|
||||||
|
{ label: "建设状态", value: data.STATUS || data.status || "-" },
|
||||||
|
{ label: "开始时间", value: data.START_TIME || data.startTime || "-" },
|
||||||
|
{ label: "预计完成", value: data.END_TIME || data.endTime || "-" },
|
||||||
|
];
|
||||||
|
case "tunnel":
|
||||||
|
return [
|
||||||
|
{ label: "隧道名称", value: data.NAME || data.name || data.GL1_SDMC || "-" },
|
||||||
|
{ label: "所属区县", value: data.COUNTY || data.county || data.GL1_QXMC || "-" },
|
||||||
|
{ label: "路线编号", value: data.ROUTE_CODE || data.routeCode || data.GL1_LXBM || "-" },
|
||||||
|
{ label: "路线名称", value: data.ROUTE_NAME || data.routeName || data.GL1_LXMC || "-" },
|
||||||
|
{ label: "隧道长度", value: data.LENGTH || data.GL1_SDCD ? `${data.LENGTH || data.GL1_SDCD}(米)` : "-" },
|
||||||
|
{ label: "隧道净宽", value: data.WIDTH || data.GL1_SDKD ? `${data.WIDTH || data.GL1_SDKD}(米)` : "-" },
|
||||||
|
{ label: "隧道净高", value: data.HEIGHT || data.GL1_SDGD ? `${data.HEIGHT || data.GL1_SDGD}(米)` : "-" },
|
||||||
|
{ label: "建成时间", value: data.BUILD_TIME || data.buildTime || data.GL1_JCSJ || "-" },
|
||||||
|
{ label: "评定等级", value: data.GRADE || data.grade || data.GL1_PDDJ || "-" },
|
||||||
|
];
|
||||||
|
case "bridge":
|
||||||
|
return [
|
||||||
|
{ label: "桥梁名称", value: data.NAME || data.name || data.GL1_QLMC || "-" },
|
||||||
|
{ label: "所属区县", value: data.COUNTY || data.county || data.GL1_QXMC || "-" },
|
||||||
|
{ label: "路线编号", value: data.ROUTE_CODE || data.routeCode || data.GL1_LXBM || "-" },
|
||||||
|
{ label: "路线名称", value: data.ROUTE_NAME || data.routeName || data.GL1_LXMC || "-" },
|
||||||
|
{ label: "桥梁长度", value: data.LENGTH || data.GL1_QLCD ? `${data.LENGTH || data.GL1_QLCD}(米)` : "-" },
|
||||||
|
{ label: "桥梁宽度", value: data.WIDTH || data.GL1_QLKD ? `${data.WIDTH || data.GL1_QLKD}(米)` : "-" },
|
||||||
|
{ label: "桥梁类型", value: data.TYPE || data.type || data.GL1_QLXZ || "-" },
|
||||||
|
{ label: "建成时间", value: data.BUILD_TIME || data.buildTime || data.GL1_JCSJ || "-" },
|
||||||
|
{ label: "评定等级", value: data.GRADE || data.grade || data.GL1_PDDJ || "-" },
|
||||||
|
];
|
||||||
|
case "road":
|
||||||
|
return [
|
||||||
|
{ label: "路段名称", value: data.NAME || data.name || data.GL1_LDMC || "-" },
|
||||||
|
{ label: "所属区县", value: data.COUNTY || data.county || data.GL1_QXMC || "-" },
|
||||||
|
{ label: "路线编号", value: data.ROUTE_CODE || data.routeCode || data.GL1_LXBM || "-" },
|
||||||
|
{ label: "路线名称", value: data.ROUTE_NAME || data.routeName || data.GL1_LXMC || "-" },
|
||||||
|
{ label: "路段长度", value: data.LENGTH || data.GL1_LDCD ? `${data.LENGTH || data.GL1_LDCD}(公里)` : "-" },
|
||||||
|
{ label: "路面类型", value: data.PAVEMENT_TYPE || data.pavementType || data.GL1_LMLX || "-" },
|
||||||
|
{ label: "车道数量", value: data.LANE_COUNT || data.laneCount || data.GL1_CDSL || "-" },
|
||||||
|
{ label: "设计时速", value: data.SPEED_LIMIT || data.speedLimit ? `${data.SPEED_LIMIT || data.speedLimit}(km/h)` : "-" },
|
||||||
|
];
|
||||||
|
default:
|
||||||
|
return [
|
||||||
|
{ label: "名称", value: data.NAME || data.name || "-" },
|
||||||
|
{ label: "所属区县", value: data.COUNTY || data.county || "-" },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@function vw($px) {
|
||||||
|
@return calc($px / 1920 * 100vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
padding: vw(10) vw(15);
|
||||||
|
max-height: vw(300);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: vw(10);
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
font-size: vw(13);
|
||||||
|
min-width: vw(80);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
color: #fff;
|
||||||
|
font-size: vw(13);
|
||||||
|
flex: 1;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<span class="info-value">{{ item.value }}</span>
|
<span class="info-value">{{ item.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-imgs">
|
<!-- <div class="dialog-imgs">
|
||||||
<img
|
<img
|
||||||
class="dialog-img"
|
class="dialog-img"
|
||||||
v-for="(img, index) in rescueTeamData.imgs"
|
v-for="(img, index) in rescueTeamData.imgs"
|
||||||
@ -30,7 +30,7 @@
|
|||||||
:src="img"
|
:src="img"
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> -->
|
||||||
</template>
|
</template>
|
||||||
</base-dialog>
|
</base-dialog>
|
||||||
</template>
|
</template>
|
||||||
@ -47,9 +47,9 @@ const props = defineProps({
|
|||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({
|
default: () => ({
|
||||||
title: "隧道信息",
|
title: "项目信息",
|
||||||
items: [
|
items: [
|
||||||
{ label: "隧道名称", value: "蔺市隧道右线" },
|
{ label: "项目名称", value: "蔺市隧道右线" },
|
||||||
{ label: "编号", value: "G212线" },
|
{ label: "编号", value: "G212线" },
|
||||||
{ label: "所属区县", value: "涪陵" },
|
{ label: "所属区县", value: "涪陵" },
|
||||||
{ label: "隧道长度", value: "1782(米)" },
|
{ label: "隧道长度", value: "1782(米)" },
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
class="nav-item"
|
class="nav-item"
|
||||||
:class="{ active: activeIndex === index }"
|
:class="{ active: activeIndex === index }"
|
||||||
@click="activeIndex = index"
|
@click="handleClick(index)"
|
||||||
>
|
>
|
||||||
<div class="nav-icon-box">
|
<div class="nav-icon-box">
|
||||||
<!-- <i :class="item.icon"></i> -->
|
<!-- <i :class="item.icon"></i> -->
|
||||||
@ -22,6 +22,7 @@
|
|||||||
class="clear-icon"
|
class="clear-icon"
|
||||||
src="../../assets/RiskWarning_img/清除icon@2x.png"
|
src="../../assets/RiskWarning_img/清除icon@2x.png"
|
||||||
alt=""
|
alt=""
|
||||||
|
@click="clearFilters"
|
||||||
/>
|
/>
|
||||||
<div class="panel-header">
|
<div class="panel-header">
|
||||||
<div class="header-title">气象预警监测</div>
|
<div class="header-title">气象预警监测</div>
|
||||||
@ -117,7 +118,7 @@ import bridgeIconIcon1 from "../../assets/RiskWarning_img/桥梁icon1@2x.png";
|
|||||||
import roadIconIcon1 from "../../assets/RiskWarning_img/线路路段icon1@2x.png";
|
import roadIconIcon1 from "../../assets/RiskWarning_img/线路路段icon1@2x.png";
|
||||||
import teamIconIcon1 from "../../assets/RiskWarning_img/队伍icon1@2x.png";
|
import teamIconIcon1 from "../../assets/RiskWarning_img/队伍icon1@2x.png";
|
||||||
|
|
||||||
const activeIndex = ref(0);
|
const activeIndex = ref(-1);
|
||||||
|
|
||||||
const menuItems = [
|
const menuItems = [
|
||||||
{
|
{
|
||||||
@ -241,7 +242,24 @@ const cellStyle = () => ({
|
|||||||
const rowClassName = ({ rowIndex }) => {
|
const rowClassName = ({ rowIndex }) => {
|
||||||
return rowIndex % 2 === 0 ? "even-row" : "odd-row";
|
return rowIndex % 2 === 0 ? "even-row" : "odd-row";
|
||||||
};
|
};
|
||||||
|
const emit = defineEmits(["changeActiveIndex", "clearMapMarkers"]);
|
||||||
|
// 点击切换导航项
|
||||||
|
const handleClick = (index) => {
|
||||||
|
activeIndex.value = index;
|
||||||
|
emit("changeActiveIndex", index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清除筛选条件
|
||||||
|
const clearFilters = () => {
|
||||||
|
filters.value = {
|
||||||
|
red: false,
|
||||||
|
blue: false,
|
||||||
|
orange: false,
|
||||||
|
yellow: false,
|
||||||
|
};
|
||||||
|
// 触发清除地图标记事件
|
||||||
|
emit("clearMapMarkers");
|
||||||
|
};
|
||||||
// 表格自动滚动相关
|
// 表格自动滚动相关
|
||||||
const tableRef = ref(null);
|
const tableRef = ref(null);
|
||||||
const isScrolling = ref(true);
|
const isScrolling = ref(true);
|
||||||
|
|||||||
@ -16,21 +16,47 @@
|
|||||||
:z-index="zIndex"
|
:z-index="zIndex"
|
||||||
:width="width"
|
:width="width"
|
||||||
></TongnanCenterCardDialog>
|
></TongnanCenterCardDialog>
|
||||||
|
<tunnelInfoDialog
|
||||||
|
v-model:visible="tunnelDialogVisible"
|
||||||
|
:data="tunnelDialogData"
|
||||||
|
/>
|
||||||
|
<mapInfoDialog
|
||||||
|
v-model:visible="mapInfoDialogVisible"
|
||||||
|
:type="mapInfoDialogType"
|
||||||
|
:data="mapInfoDialogData"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted } from "vue";
|
import { ref, onMounted, onUnmounted, watch, defineExpose } from "vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { request } from "@/utils/request";
|
import { request } from "@/utils/request";
|
||||||
import TongnanCenterCardDialog from "@/views/RiskWarning/Dialog/tongnanCenterCardDialog.vue";
|
import TongnanCenterCardDialog from "@/views/RiskWarning/Dialog/tongnanCenterCardDialog.vue";
|
||||||
|
|
||||||
|
import projectIcon from "../../../assets/MaMap_img/项目@2x.png";
|
||||||
|
import bridgeIcon from "../../../assets/MaMap_img/桥梁icon@2x.png";
|
||||||
|
import tunnelIcon from "../../../assets/MaMap_img/蓝色@2x1.png";
|
||||||
|
import tunnelLineIcon from "../../../assets/MaMap_img/线路icon定位@2x.png";
|
||||||
|
import tunnelIcon2 from "../../../assets/MaMap_img/隧洞icon@2x.png";
|
||||||
|
import rescueTeamIcon from "../../../assets/MaMap_img/队伍icon@2x.png";
|
||||||
|
|
||||||
|
import tunnelInfoDialog from "../Dialog/tunnelInfoDialog.vue";
|
||||||
|
import mapInfoDialog from "../Dialog/mapInfoDialog.vue";
|
||||||
|
|
||||||
const mapContainer = ref(null);
|
const mapContainer = ref(null);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const error = ref(null);
|
const error = ref(null);
|
||||||
let mapInstance = null;
|
let mapInstance = null;
|
||||||
let geoJsonLayer = null;
|
let geoJsonLayer = null;
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
activeIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: -1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// 定义 emits
|
// 定义 emits
|
||||||
const emit = defineEmits(["districtClick"]);
|
const emit = defineEmits(["districtClick"]);
|
||||||
|
|
||||||
@ -38,6 +64,27 @@ const emit = defineEmits(["districtClick"]);
|
|||||||
const selectedDistrict = ref(null);
|
const selectedDistrict = ref(null);
|
||||||
let selectedLayer = null;
|
let selectedLayer = null;
|
||||||
|
|
||||||
|
// 隧道信息弹窗
|
||||||
|
const tunnelDialogVisible = ref(false);
|
||||||
|
const tunnelDialogData = ref({});
|
||||||
|
|
||||||
|
// 地图信息弹窗
|
||||||
|
const mapInfoDialogVisible = ref(false);
|
||||||
|
const mapInfoDialogType = ref("project");
|
||||||
|
const mapInfoDialogData = ref({});
|
||||||
|
|
||||||
|
// 打开地图信息弹窗
|
||||||
|
const openMapInfoDialog = (type, data) => {
|
||||||
|
mapInfoDialogType.value = type;
|
||||||
|
mapInfoDialogData.value = data;
|
||||||
|
mapInfoDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开隧道信息弹窗(兼容旧代码)
|
||||||
|
const openTunnelDialog = (data) => {
|
||||||
|
openMapInfoDialog("tunnel", data);
|
||||||
|
};
|
||||||
|
|
||||||
// 受影响对象数据
|
// 受影响对象数据
|
||||||
const affectedCountyData = ref({
|
const affectedCountyData = ref({
|
||||||
byName: {},
|
byName: {},
|
||||||
@ -68,6 +115,265 @@ const getAffectedCountyData = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const affectedBridgeData = ref([]);
|
||||||
|
// 获取受影响桥梁数据
|
||||||
|
const getAffectedBridgeData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "snow-ops-platform/weather-warning/affected-object/bridge",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: "2025-03-03 12:33:00",
|
||||||
|
end: "2025-07-30 12:33:00",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (res.code === "00000" && res.data) {
|
||||||
|
res.data.forEach((item) => {
|
||||||
|
item.COORDINATE_POINT = [item.GL1_QLJD, item.GL1_QLWD];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
affectedBridgeData.value = res.data;
|
||||||
|
|
||||||
|
addProjectMarkers(res.data, bridgeIcon, "bridge");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取受影响桥梁数据失败:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const affectedTunnelData = ref([]);
|
||||||
|
|
||||||
|
const tunnelInfoDialogRef = ref(null);
|
||||||
|
// 获取受影响隧道数据
|
||||||
|
const getAffectedTunnelData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "snow-ops-platform/weather-warning/affected-object/tunnel",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: "2025-03-03 12:33:00",
|
||||||
|
end: "2025-07-30 12:33:00",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("受影响隧道数据:", res);
|
||||||
|
if (res.code === "00000" && res.data) {
|
||||||
|
res.data.forEach((item) => {
|
||||||
|
item.COORDINATE_POINT = [
|
||||||
|
Number(item.GL1_SDJD2),
|
||||||
|
Number(item.GL1_SDWD2),
|
||||||
|
];
|
||||||
|
});
|
||||||
|
tunnelInfoDialogRef.value = res.data;
|
||||||
|
console.log("受影响隧道数据:", res.data);
|
||||||
|
|
||||||
|
addProjectMarkers(res.data, tunnelIcon2, "tunnel");
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取受影响隧道数据失败:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const affectedProjectData = ref([]);
|
||||||
|
|
||||||
|
// 获取受影响项目数据
|
||||||
|
const getAffectedProjectData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "snow-ops-platform/weather-warning/affected-object/project",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: "2025-03-03 12:33:00",
|
||||||
|
end: "2025-07-30 12:33:00",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("受影响项目数据:", res);
|
||||||
|
if (res.code === "00000" && res.data) {
|
||||||
|
console.log("项目数据条数:", res.data.length);
|
||||||
|
// 解析坐标数据
|
||||||
|
const parsedData = res.data.map((item) => {
|
||||||
|
const newItem = { ...item };
|
||||||
|
if (item.COORDINATE_POINT) {
|
||||||
|
console.log("原始坐标:", item.COORDINATE_POINT);
|
||||||
|
newItem.COORDINATE_POINT = item.COORDINATE_POINT.substring(
|
||||||
|
6,
|
||||||
|
item.COORDINATE_POINT.length - 1,
|
||||||
|
)
|
||||||
|
.split(" ")
|
||||||
|
.reverse();
|
||||||
|
console.log("解析后坐标:", newItem.COORDINATE_POINT);
|
||||||
|
}
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
affectedProjectData.value = parsedData;
|
||||||
|
// 在地图上添加项目标记
|
||||||
|
console.log("开始添加项目标记...");
|
||||||
|
addProjectMarkers(parsedData, projectIcon, "project");
|
||||||
|
} else {
|
||||||
|
console.warn("没有获取到项目数据或返回码错误:", res);
|
||||||
|
}
|
||||||
|
return res.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取受影响项目数据失败:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const affectedRoadSectionData = ref([]);
|
||||||
|
// 获取受影响路段数据
|
||||||
|
const getAffectedRoadSectionData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "snow-ops-platform/weather-warning/affected-object/road-section",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: "2025-03-03 12:33:00",
|
||||||
|
end: "2025-07-30 12:33:00",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("受影响路段数据:", res);
|
||||||
|
if (res.code === "00000" && res.data) {
|
||||||
|
res.data.forEach((item) => {
|
||||||
|
item.COORDINATE_POINT = JSON.parse(item.STARTPOINT);
|
||||||
|
});
|
||||||
|
affectedRoadSectionData.value = res.data;
|
||||||
|
// 在地图上添加项目标记
|
||||||
|
console.log("开始添加项目标记...");
|
||||||
|
|
||||||
|
addProjectMarkers(affectedRoadSectionData.value, tunnelLineIcon, "road");
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取受影响路段数据失败:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const emergencyForceData = ref([]);
|
||||||
|
// 获取应急力量数据
|
||||||
|
const getEmergencyForceData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await request({
|
||||||
|
url: "/snow-ops-platform/yhYjll/list",
|
||||||
|
method: "GET",
|
||||||
|
params: {
|
||||||
|
start: "2025-03-03 12:33:00",
|
||||||
|
end: "2025-07-30 12:33:00",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("应急力量数据:", res);
|
||||||
|
if (
|
||||||
|
res.code === "00000" &&
|
||||||
|
res.data
|
||||||
|
) {
|
||||||
|
// 解析坐标数据
|
||||||
|
const parsedData = res.data.map((item) => {
|
||||||
|
const newItem = { ...item };
|
||||||
|
newItem.COORDINATE_POINT = [item.gl1Lng, item.gl1Lat];
|
||||||
|
console.log("解析后坐标:", newItem.COORDINATE_POINT);
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
emergencyForceData.value = parsedData;
|
||||||
|
|
||||||
|
// 在地图上添加应急力量标记
|
||||||
|
console.log("开始添加应急力量标记...", parsedData);
|
||||||
|
addProjectMarkers(parsedData, tunnelIcon, "tunnel");
|
||||||
|
} else {
|
||||||
|
console.warn("没有获取到应急力量数据或返回码错误:", res);
|
||||||
|
}
|
||||||
|
return res.data || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取应急力量数据失败:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let projectMarkers = []; // 存储项目标记
|
||||||
|
|
||||||
|
// 清除项目标记
|
||||||
|
const clearProjectMarkers = () => {
|
||||||
|
projectMarkers.forEach((marker) => {
|
||||||
|
if (mapInstance) {
|
||||||
|
mapInstance.removeLayer(marker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
projectMarkers = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
// 在地图上添加项目标记
|
||||||
|
const addProjectMarkers = (data, iconUrl, type = "project") => {
|
||||||
|
console.log(
|
||||||
|
"addProjectMarkers 被调用, mapInstance:",
|
||||||
|
!!mapInstance,
|
||||||
|
"数据条数:",
|
||||||
|
data?.length,
|
||||||
|
"类型:",
|
||||||
|
type,
|
||||||
|
);
|
||||||
|
if (!mapInstance) {
|
||||||
|
console.warn("mapInstance 未初始化,无法添加标记");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!data || data.length === 0) {
|
||||||
|
console.warn("没有数据,无法添加标记");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 清除之前的标记
|
||||||
|
// clearProjectMarkers();
|
||||||
|
|
||||||
|
// 创建自定义图标
|
||||||
|
const projectIconObj = window.L.icon({
|
||||||
|
iconUrl: iconUrl,
|
||||||
|
iconSize: [30, 30],
|
||||||
|
iconAnchor: [10, 10],
|
||||||
|
popupAnchor: [0, -10],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 遍历数据添加标记
|
||||||
|
data.forEach((item) => {
|
||||||
|
if (item.COORDINATE_POINT && item.COORDINATE_POINT.length === 2) {
|
||||||
|
// COORDINATE_POINT 格式: [经度, 纬度]
|
||||||
|
// Leaflet 需要: [纬度, 经度]
|
||||||
|
const lng = item.COORDINATE_POINT[0];
|
||||||
|
const lat = item.COORDINATE_POINT[1];
|
||||||
|
|
||||||
|
const latNum = parseFloat(lat);
|
||||||
|
const lngNum = parseFloat(lng);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"项目坐标:",
|
||||||
|
item.NAME || item.name,
|
||||||
|
"纬度:",
|
||||||
|
latNum,
|
||||||
|
"经度:",
|
||||||
|
lngNum,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isNaN(latNum) && !isNaN(lngNum)) {
|
||||||
|
const marker = window.L.marker([latNum, lngNum], {
|
||||||
|
icon: projectIconObj,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击 marker 打开对应类型的信息弹窗
|
||||||
|
marker.on("click", () => {
|
||||||
|
openMapInfoDialog(type, item);
|
||||||
|
});
|
||||||
|
|
||||||
|
marker.addTo(mapInstance);
|
||||||
|
projectMarkers.push(marker);
|
||||||
|
} else {
|
||||||
|
console.warn("无效的坐标:", item.COORDINATE_POINT, item);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.warn("缺少坐标数据:", item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`已添加 ${projectMarkers.length} 个项目标记`);
|
||||||
|
};
|
||||||
|
|
||||||
// 确定主要预警颜色(出现最多的预警等级)
|
// 确定主要预警颜色(出现最多的预警等级)
|
||||||
const getMainWarningColor = (levels) => {
|
const getMainWarningColor = (levels) => {
|
||||||
if (!levels || Object.keys(levels).length === 0) return "#1890ff"; // 默认蓝色
|
if (!levels || Object.keys(levels).length === 0) return "#1890ff"; // 默认蓝色
|
||||||
@ -97,18 +403,6 @@ const getMainWarningColor = (levels) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 根据预警等级获取颜色
|
|
||||||
const getColorByLevel = (level) => {
|
|
||||||
const colorMap = {
|
|
||||||
红色预警: "#FF4D4F",
|
|
||||||
橙色预警: "#EC7345",
|
|
||||||
黄色预警: "#FBC23C",
|
|
||||||
蓝色预警: "#3799FC",
|
|
||||||
未知: "#1890ff",
|
|
||||||
};
|
|
||||||
return colorMap[level] || "#1890ff";
|
|
||||||
};
|
|
||||||
|
|
||||||
// 统计各区县的预警数量(按预警等级区分)
|
// 统计各区县的预警数量(按预警等级区分)
|
||||||
const countWarningsByCounty = (data) => {
|
const countWarningsByCounty = (data) => {
|
||||||
if (!data || !Array.isArray(data)) return {};
|
if (!data || !Array.isArray(data)) return {};
|
||||||
@ -326,7 +620,17 @@ const simplifyDistrictName = (name) => {
|
|||||||
};
|
};
|
||||||
return nameMap[name] || name;
|
return nameMap[name] || name;
|
||||||
};
|
};
|
||||||
|
// 根据预警等级获取颜色
|
||||||
|
const getColorByLevel = (level) => {
|
||||||
|
const colorMap = {
|
||||||
|
红色预警: "#FF4D4F",
|
||||||
|
橙色预警: "#EC7345",
|
||||||
|
黄色预警: "#705D42",
|
||||||
|
蓝色预警: "#3799FC",
|
||||||
|
未知: "#1890ff",
|
||||||
|
};
|
||||||
|
return colorMap[level] || "#1890ff";
|
||||||
|
};
|
||||||
// 初始化地图
|
// 初始化地图
|
||||||
const initMap = (geoJsonData) => {
|
const initMap = (geoJsonData) => {
|
||||||
if (!mapContainer.value) return;
|
if (!mapContainer.value) return;
|
||||||
@ -362,7 +666,8 @@ const initMap = (geoJsonData) => {
|
|||||||
// 添加 GeoJSON 图层
|
// 添加 GeoJSON 图层
|
||||||
geoJsonLayer = new window.L.GeoJSON(geoJsonData, {
|
geoJsonLayer = new window.L.GeoJSON(geoJsonData, {
|
||||||
style: (feature) => {
|
style: (feature) => {
|
||||||
const districtName = feature.properties.name;
|
// const districtName = feature.properties.name;
|
||||||
|
const districtName = simplifyDistrictName(feature.properties.name);
|
||||||
let fillColor = "#132C44"; // 默认
|
let fillColor = "#132C44"; // 默认
|
||||||
// 如果有预警统计数据,应用主要预警颜色
|
// 如果有预警统计数据,应用主要预警颜色
|
||||||
if (
|
if (
|
||||||
@ -378,9 +683,9 @@ const initMap = (geoJsonData) => {
|
|||||||
return {
|
return {
|
||||||
fillColor: fillColor,
|
fillColor: fillColor,
|
||||||
weight: 1.5,
|
weight: 1.5,
|
||||||
opacity: 0.6,
|
opacity: 0.5,
|
||||||
color: "#40a9ff",
|
color: "#40a9ff",
|
||||||
fillOpacity: 1,
|
fillOpacity: 0.5,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onEachFeature: (feature, layer) => {
|
onEachFeature: (feature, layer) => {
|
||||||
@ -513,6 +818,31 @@ const initMap = (geoJsonData) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 监听 activeIndex 变化
|
||||||
|
watch(
|
||||||
|
() => props.activeIndex,
|
||||||
|
async (newVal) => {
|
||||||
|
console.log("activeIndex 变化:", newVal);
|
||||||
|
switch (newVal) {
|
||||||
|
case 0:
|
||||||
|
await getAffectedProjectData();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
await getAffectedTunnelData();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
await getAffectedBridgeData();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
await getAffectedRoadSectionData();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: false },
|
||||||
|
);
|
||||||
|
|
||||||
// 组件挂载时加载地图
|
// 组件挂载时加载地图
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取受影响对象数据
|
// 获取受影响对象数据
|
||||||
@ -546,6 +876,12 @@ onUnmounted(() => {
|
|||||||
mapInstance = null;
|
mapInstance = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 暴露方法给父组件调用
|
||||||
|
defineExpose({
|
||||||
|
getEmergencyForceData,
|
||||||
|
clearProjectMarkers,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@ -659,6 +995,9 @@ onUnmounted(() => {
|
|||||||
// Leaflet 地图样式覆盖
|
// Leaflet 地图样式覆盖
|
||||||
:deep(.leaflet-container) {
|
:deep(.leaflet-container) {
|
||||||
background: #0f1c2e !important;
|
background: #0f1c2e !important;
|
||||||
|
.leaflet-popup {
|
||||||
|
left: -20px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.leaflet-popup-content-wrapper {
|
.leaflet-popup-content-wrapper {
|
||||||
background: rgba(24, 144, 255, 0.95);
|
background: rgba(24, 144, 255, 0.95);
|
||||||
@ -693,4 +1032,15 @@ onUnmounted(() => {
|
|||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project-popup {
|
||||||
|
width: vw(120);
|
||||||
|
height: vw(20);
|
||||||
|
color: #fff;
|
||||||
|
font-size: vw(12);
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -93,6 +93,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<right
|
<right
|
||||||
|
@openResourceDetail="openResourceDetail"
|
||||||
@openClearanceSituation="openDialog('clearanceSituation')"
|
@openClearanceSituation="openDialog('clearanceSituation')"
|
||||||
@openControlSituation="openDialog('controlSituation')"
|
@openControlSituation="openDialog('controlSituation')"
|
||||||
></right>
|
></right>
|
||||||
@ -101,14 +102,14 @@
|
|||||||
<div class="center">
|
<div class="center">
|
||||||
<!-- 地图底层 -->
|
<!-- 地图底层 -->
|
||||||
<div class="map-layer">
|
<div class="map-layer">
|
||||||
<ChongqingMap />
|
<ChongqingMap ref="chongqingMapRef" :activeIndex="activeIndex" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 地图遮罩层 -->
|
<!-- 地图遮罩层 -->
|
||||||
<div class="map-mask" aria-hidden="true"></div>
|
<div class="map-mask" aria-hidden="true"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
<bottom></bottom>
|
<bottom @changeActiveIndex="changeActiveIndex" @clearMapMarkers="clearMapMarkers"></bottom>
|
||||||
</div>
|
</div>
|
||||||
<top class="top" @openAIResult="openDialog('aiWarningResult')"></top>
|
<top class="top" @openAIResult="openDialog('aiWarningResult')"></top>
|
||||||
|
|
||||||
@ -306,6 +307,40 @@ const dialogVisible = ref({
|
|||||||
warningSituation: false,
|
warningSituation: false,
|
||||||
tunnelInfo: false
|
tunnelInfo: false
|
||||||
});
|
});
|
||||||
|
const activeIndex = ref(0);
|
||||||
|
|
||||||
|
// 地图组件引用
|
||||||
|
const chongqingMapRef = ref(null);
|
||||||
|
|
||||||
|
// 切换导航项时触发
|
||||||
|
const changeActiveIndex = (index) => {
|
||||||
|
activeIndex.value = index;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开资源详情(队伍、人员、装备、物资)
|
||||||
|
const openResourceDetail = (item) => {
|
||||||
|
console.log("打开资源详情:", item);
|
||||||
|
// 判断是否为队伍或人员
|
||||||
|
if (item.label === "全市普通公路抢险队伍" || item.label === "人员") {
|
||||||
|
// 调用地图组件的获取应急力量方法
|
||||||
|
if (chongqingMapRef.value) {
|
||||||
|
chongqingMapRef.value.getEmergencyForceData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 打开对应的弹窗
|
||||||
|
const key = item.label.toLowerCase().replace(/[^a-z]/g, "");
|
||||||
|
if (dialogVisible.value[key] !== undefined) {
|
||||||
|
dialogVisible.value[key] = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清除地图标记
|
||||||
|
const clearMapMarkers = () => {
|
||||||
|
console.log("清除地图标记");
|
||||||
|
if (chongqingMapRef.value) {
|
||||||
|
chongqingMapRef.value.clearProjectMarkers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = (dialogName) => {
|
const openDialog = (dialogName) => {
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
v-for="(item, index) in resourceData"
|
v-for="(item, index) in resourceData"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="resource-item"
|
class="resource-item"
|
||||||
|
@click="handleResourceClick(item)"
|
||||||
>
|
>
|
||||||
<!-- <div class="resource-icon" :class="item.iconClass"></div> -->
|
<!-- <div class="resource-icon" :class="item.iconClass"></div> -->
|
||||||
<img class="resource-icon" :src="item.img" alt="" />
|
<img class="resource-icon" :src="item.img" alt="" />
|
||||||
@ -215,7 +216,11 @@ import icon62 from "../../assets/RiskWarning_img/路径62@2x.png";
|
|||||||
import icon621 from "../../assets/RiskWarning_img/路径62@2x (1).png";
|
import icon621 from "../../assets/RiskWarning_img/路径62@2x (1).png";
|
||||||
import icon622 from "../../assets/RiskWarning_img/路径62@2x (2).png";
|
import icon622 from "../../assets/RiskWarning_img/路径62@2x (2).png";
|
||||||
|
|
||||||
const emit = defineEmits(["openClearanceSituation", "openControlSituation"]);
|
const emit = defineEmits([
|
||||||
|
"openClearanceSituation",
|
||||||
|
"openControlSituation",
|
||||||
|
"openResourceDetail",
|
||||||
|
]);
|
||||||
|
|
||||||
// 组件挂载时获取数据
|
// 组件挂载时获取数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@ -251,6 +256,7 @@ const getYhYjllList = async () => {
|
|||||||
resourceData.value[1].unit = "人";
|
resourceData.value[1].unit = "人";
|
||||||
}
|
}
|
||||||
resourceData.value[0].value = gl1Yjllmcs;
|
resourceData.value[0].value = gl1Yjllmcs;
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取应急力量列表失败:", error);
|
console.error("获取应急力量列表失败:", error);
|
||||||
@ -369,6 +375,11 @@ const resourceData = ref([
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 点击资源项
|
||||||
|
const handleResourceClick = (item) => {
|
||||||
|
emit("openResourceDetail", item);
|
||||||
|
};
|
||||||
|
|
||||||
// 管控路段数据
|
// 管控路段数据
|
||||||
const controlData1 = [
|
const controlData1 = [
|
||||||
{ label: "封闭管控数", value: "40" },
|
{ label: "封闭管控数", value: "40" },
|
||||||
|
|||||||