Merge branch 'dev' of http://222.212.85.86:8222/bdzl2/bxztApp into dev
This commit is contained in:
commit
26d7a1ecbf
@ -4,6 +4,7 @@
|
|||||||
<van-field
|
<van-field
|
||||||
v-model="displayValue"
|
v-model="displayValue"
|
||||||
:label="label"
|
:label="label"
|
||||||
|
:required="required"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:readonly="true"
|
:readonly="true"
|
||||||
@ -69,6 +70,10 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
// 占位符
|
// 占位符
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -438,4 +443,4 @@ watch(() => props.modelValue, () => {
|
|||||||
.picker-wrapper.has-time .van-time-picker {
|
.picker-wrapper.has-time .van-time-picker {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
<van-field
|
<van-field
|
||||||
:modelValue="displayValue"
|
:modelValue="displayValue"
|
||||||
:label="label"
|
:label="label"
|
||||||
|
:required="required"
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:readonly="true"
|
:readonly="true"
|
||||||
@ -49,6 +50,10 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
|
required: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
// 占位符
|
// 占位符
|
||||||
placeholder: {
|
placeholder: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -161,4 +166,4 @@ const onConfirm = ({ selectedValues, selectedOptions }) => {
|
|||||||
:deep(.van-field__control--readonly) {
|
:deep(.van-field__control--readonly) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -12,35 +12,33 @@
|
|||||||
</div>
|
</div>
|
||||||
<CurrentSite />
|
<CurrentSite />
|
||||||
<div class="list-panel">
|
<div class="list-panel">
|
||||||
<CardItem v-for="(item, index) in list" :key="index" :title="getEventTitle(item)" @click="handleClickItem(item)">
|
<van-list :loading="loading" :finished="finished" finished-text="没有更多了" @load="handleLoadMore">
|
||||||
<template #headerExtra>
|
<CardItem v-for="(item, index) in list" :key="index" :title="item.eventName" @click="handleClickItem(item)">
|
||||||
<van-tag :type="getEventStatusType(item.eventStatus)" plain size="medium">
|
<template #headerExtra>
|
||||||
{{ getEventStatusText(item.eventStatus) }}
|
<van-tag :type="getEventStatusType(item.eventStatus)" plain size="medium">
|
||||||
</van-tag>
|
{{ getEventStatusText(item.eventStatus) }}
|
||||||
</template>
|
</van-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
<div class="info-block">
|
<div class="info-block">
|
||||||
<div class="time-box">
|
<div class="time-box">
|
||||||
<span class="info-label">发生时间:</span>
|
<span class="info-label">发生时间:</span>
|
||||||
<span class="info-value">{{ item.occurTime || '-' }}</span>
|
<span class="info-value">{{ item.occurTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="time-box">
|
||||||
|
<span class="info-label">预计恢复时间:</span>
|
||||||
|
<span class="info-value">{{ item.expectRecoverTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="disaster-type-wrapper">
|
||||||
|
<van-tag class="tag" type="primary" size="medium" plain>{{ getDisasterTypeText(item) }}</van-tag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="time-box">
|
|
||||||
<span class="info-label">预计恢复时间:</span>
|
|
||||||
<span class="info-value">{{ item.expectRecoverTime || '-' }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="disaster-type-wrapper">
|
|
||||||
<van-tag class="tag" type="primary" size="medium" plain>{{ getDisasterTypeText(item) }}</van-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<van-icon class="jump-icon-absolute" name="arrow" />
|
<van-icon class="jump-icon-absolute" name="arrow" />
|
||||||
</CardItem>
|
</CardItem>
|
||||||
|
</van-list>
|
||||||
|
|
||||||
<div v-if="loading" class="loading-wrapper">
|
<!-- <EmptyBox v-if="!loading && loaded && list.length === 0" :placeholder="emptyText" /> -->
|
||||||
<van-loading size="24px" vertical>加载中...</van-loading>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<EmptyBox v-if="!loading && list.length === 0" :placeholder="emptyText" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<van-button type="primary" class="footer-btn" @click="handleAdd">灾害填报</van-button>
|
<van-button type="primary" class="footer-btn" @click="handleAdd">灾害填报</van-button>
|
||||||
@ -52,8 +50,8 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { RouterLink, useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { showToast, Tag as VanTag, Loading as VanLoading, Icon as VanIcon, Button as VanButton, showImagePreview } from 'vant'
|
import { showToast, Tag as VanTag, List as VanList, Icon as VanIcon, Button as VanButton } from 'vant'
|
||||||
import PageContainer from '@/components/PageContainer.vue'
|
import PageContainer from '@/components/PageContainer.vue'
|
||||||
import SearchInput from '@/components/SearchInput.vue'
|
import SearchInput from '@/components/SearchInput.vue'
|
||||||
import CardItem from '@/components/CardItem.vue'
|
import CardItem from '@/components/CardItem.vue'
|
||||||
@ -73,6 +71,14 @@ const list = ref([])
|
|||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const loaded = ref(false)
|
||||||
|
|
||||||
|
const finished = ref(false)
|
||||||
|
|
||||||
|
const pageNum = ref(1)
|
||||||
|
|
||||||
|
const pageSize = 10
|
||||||
|
|
||||||
// 空状态文本
|
// 空状态文本
|
||||||
const emptyText = ref('暂无相关灾毁信息')
|
const emptyText = ref('暂无相关灾毁信息')
|
||||||
|
|
||||||
@ -92,6 +98,7 @@ const disasterTypes = [
|
|||||||
{ label: '行道树倒塌', value: '行道树倒塌' },
|
{ label: '行道树倒塌', value: '行道树倒塌' },
|
||||||
{ label: '积水', value: '积水' },
|
{ label: '积水', value: '积水' },
|
||||||
{ label: '积雪', value: '积雪' },
|
{ label: '积雪', value: '积雪' },
|
||||||
|
{ label: '冰雪灾害', value: '冰雪灾害' },
|
||||||
{ label: '其他', value: '其他' }
|
{ label: '其他', value: '其他' }
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -138,18 +145,25 @@ const getShortTypeName = (type) => {
|
|||||||
积水: '积水',
|
积水: '积水',
|
||||||
积雪: '积雪',
|
积雪: '积雪',
|
||||||
其他: '其他',
|
其他: '其他',
|
||||||
未抢险: '待抢险',
|
冰雪灾害: '冰雪'
|
||||||
抢险中: '抢险中',
|
|
||||||
已完成: '已完成',
|
|
||||||
高速公路: '高速',
|
|
||||||
国道: '国道',
|
|
||||||
省道: '省道'
|
|
||||||
}
|
}
|
||||||
return typeMap[type] || (type ? type.substring(0, 2) : '全部')
|
return typeMap[type] || (type ? type.substring(0, 2) : '全部')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取灾毁列表数据
|
// 获取灾毁列表数据
|
||||||
const getDisasterList = async (keyword = '', disasterType = null) => {
|
const getDisasterList = async ({ reset = false } = {}) => {
|
||||||
|
console.log("loading.value", loading.value)
|
||||||
|
if (loading.value) return
|
||||||
|
|
||||||
|
if (reset) {
|
||||||
|
pageNum.value = 1
|
||||||
|
finished.value = false
|
||||||
|
loaded.value = false
|
||||||
|
list.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finished.value) return
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -157,13 +171,14 @@ const getDisasterList = async (keyword = '', disasterType = null) => {
|
|||||||
url: '/snow-ops-platform/unified-disaster/list',
|
url: '/snow-ops-platform/unified-disaster/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
pageSize: 999,
|
pageNum: pageNum.value,
|
||||||
keyword: keyword.trim(),
|
pageSize,
|
||||||
roadConditionType: disasterType || undefined
|
keyword: searchValue.value.trim(),
|
||||||
|
roadConditionType: selectedDisasterType.value || undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (result?.data?.records) {
|
if (result?.data?.records) {
|
||||||
list.value = result.data.records.map((item) => ({
|
const records = result.data.records.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
// 数据转换,确保前端使用的字段存在
|
// 数据转换,确保前端使用的字段存在
|
||||||
title: getEventTitle(item),
|
title: getEventTitle(item),
|
||||||
@ -171,28 +186,45 @@ const getDisasterList = async (keyword = '', disasterType = null) => {
|
|||||||
occurTime: item.occurTime,
|
occurTime: item.occurTime,
|
||||||
estimateRecoverTime: item.expectRecoverTime
|
estimateRecoverTime: item.expectRecoverTime
|
||||||
}))
|
}))
|
||||||
|
list.value = reset ? records : [...list.value, ...records]
|
||||||
|
const total = Number(result.data.total || 0)
|
||||||
|
finished.value = list.value.length >= total || records.length < pageSize
|
||||||
|
pageNum.value += 1
|
||||||
} else {
|
} else {
|
||||||
showToast(result.message || '获取数据失败')
|
showToast(result.message || '获取数据失败')
|
||||||
list.value = []
|
if (reset) {
|
||||||
|
list.value = []
|
||||||
|
}
|
||||||
|
finished.value = true
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取灾毁列表失败:', error)
|
console.error('获取灾毁列表失败:', error)
|
||||||
showToast('获取数据失败,请稍后重试')
|
showToast('获取数据失败,请稍后重试')
|
||||||
list.value = []
|
if (reset) {
|
||||||
|
list.value = []
|
||||||
|
}
|
||||||
|
finished.value = true
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
loaded.value = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索处理
|
// 搜索处理
|
||||||
const handleSearch = () => {
|
const handleSearch = () => {
|
||||||
getDisasterList(searchValue.value, selectedDisasterType.value)
|
getDisasterList({ reset: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 筛选确认
|
// 筛选确认
|
||||||
const handleFilterConfirm = (type) => {
|
const handleFilterConfirm = (type) => {
|
||||||
// selectedDisasterType 已经通过 v-model 更新,这里只需重新请求数据
|
// selectedDisasterType 已经通过 v-model 更新,这里只需重新请求数据
|
||||||
getDisasterList(searchValue.value, type)
|
selectedDisasterType.value = type
|
||||||
|
getDisasterList({ reset: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLoadMore = () => {
|
||||||
|
if (!loaded.value) return
|
||||||
|
getDisasterList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击返回
|
// 点击返回
|
||||||
@ -227,16 +259,25 @@ const handleAdd = () => {
|
|||||||
|
|
||||||
// 页面初始化加载数据
|
// 页面初始化加载数据
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDisasterList()
|
getDisasterList({ reset: true })
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
:deep(.page-content-wrapper) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.list-panel {
|
.list-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding-bottom: 80px;
|
padding-bottom: 80px;
|
||||||
|
overflow: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-wrapper {
|
.filter-wrapper {
|
||||||
@ -321,12 +362,6 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-wrapper {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
padding: 40px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.van-button) {
|
:deep(.van-button) {
|
||||||
&.active {
|
&.active {
|
||||||
background-color: #1989fa;
|
background-color: #1989fa;
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<RoadRoutesPicker
|
<RoadRoutesPicker
|
||||||
v-model="formData.event.routeNo"
|
v-model="formData.event.routeNo"
|
||||||
label="线路编号"
|
label="线路编号"
|
||||||
placeholder="请线路"
|
placeholder="请选择"
|
||||||
@change="handleRouteNoChange"
|
@change="handleRouteNoChange"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -30,26 +30,26 @@
|
|||||||
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
|
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 起点桩经度 -->
|
<!-- 起点桩经度 -->
|
||||||
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 起点桩纬度 -->
|
<!-- 起点桩纬度 -->
|
||||||
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 止点桩号 (event.endStakeNo) -->
|
<!-- 止点桩号 (event.endStakeNo) -->
|
||||||
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
|
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 止点桩经度 -->
|
<!-- 止点桩经度 -->
|
||||||
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 止点桩纬度 -->
|
<!-- 止点桩纬度 -->
|
||||||
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 受灾里程 (event.disasterMileage) -->
|
<!-- 受灾里程 (event.disasterMileage) -->
|
||||||
<van-field
|
<van-field
|
||||||
v-model="formData.event.disasterMileage"
|
v-model="formData.event.disasterMileage"
|
||||||
label="受灾里程"
|
label="受灾里程"
|
||||||
placeholder="请填写"
|
placeholder="请填写"
|
||||||
type="digit"
|
type="number"
|
||||||
>
|
>
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">公里</span>
|
<span class="field-unit">公里</span>
|
||||||
@ -93,7 +93,7 @@
|
|||||||
<van-field
|
<van-field
|
||||||
v-model="formData.report.inputManpower"
|
v-model="formData.report.inputManpower"
|
||||||
label="投入人力"
|
label="投入人力"
|
||||||
placeholder="请填写"
|
placeholder="请填写(非必填)"
|
||||||
type="number"
|
type="number"
|
||||||
>
|
>
|
||||||
<template #button>
|
<template #button>
|
||||||
@ -103,8 +103,8 @@
|
|||||||
<van-field
|
<van-field
|
||||||
v-model="formData.report.inputFunds"
|
v-model="formData.report.inputFunds"
|
||||||
label="投入资金"
|
label="投入资金"
|
||||||
placeholder="请填写"
|
placeholder="请填写(非必填)"
|
||||||
type="digit"
|
type="number"
|
||||||
>
|
>
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">万元</span>
|
<span class="field-unit">万元</span>
|
||||||
@ -113,8 +113,8 @@
|
|||||||
<van-field
|
<van-field
|
||||||
v-model="formData.report.inputEquipment"
|
v-model="formData.report.inputEquipment"
|
||||||
label="投入设备"
|
label="投入设备"
|
||||||
placeholder="请填写"
|
placeholder="请填写(非必填)"
|
||||||
type="digit"
|
type="number"
|
||||||
>
|
>
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">台/班</span>
|
<span class="field-unit">台/班</span>
|
||||||
@ -127,7 +127,7 @@
|
|||||||
v-model="formData.report.hasStrandedVehicles"
|
v-model="formData.report.hasStrandedVehicles"
|
||||||
:options="options['haveOrNot']"
|
:options="options['haveOrNot']"
|
||||||
label="有无车辆滞留"
|
label="有无车辆滞留"
|
||||||
placeholder="请选择"
|
placeholder="请选择(非必填)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<van-field
|
<van-field
|
||||||
@ -136,15 +136,15 @@
|
|||||||
type="number"
|
type="number"
|
||||||
label="滞留车辆数"
|
label="滞留车辆数"
|
||||||
center
|
center
|
||||||
placeholder="请填写"
|
placeholder="请填写(非必填)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<van-field v-model="formData.report.siteDescription" label="现场描述" placeholder="请填写" type="textarea" rows="2" autosize />
|
<van-field v-model="formData.report.siteDescription" label="现场描述" placeholder="请填写(非必填)" type="textarea" rows="2" autosize />
|
||||||
|
|
||||||
<BaseDatePicker
|
<BaseDatePicker
|
||||||
v-model="formData.report.actualRecoverTime"
|
v-model="formData.report.actualRecoverTime"
|
||||||
label="实际恢复时间"
|
label="实际恢复时间"
|
||||||
placeholder="请选择时间"
|
placeholder="请选择时间(非必填)"
|
||||||
:min-date="minDate"
|
:min-date="minDate"
|
||||||
:max-date="maxDate"
|
:max-date="maxDate"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
@ -272,10 +272,26 @@ const validate = () => {
|
|||||||
showToast('请输入起点桩号');
|
showToast('请输入起点桩号');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (isEmpty(formData.value.event?.startStakeLng)) {
|
||||||
|
showToast('请输入起点桩经度');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.startStakeLat)) {
|
||||||
|
showToast('请输入起点桩纬度');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (isEmpty(formData.value.event?.endStakeNo)) {
|
if (isEmpty(formData.value.event?.endStakeNo)) {
|
||||||
showToast('请输入止点桩号');
|
showToast('请输入止点桩号');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (isEmpty(formData.value.event?.endStakeLng)) {
|
||||||
|
showToast('请输入止点桩经度');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.endStakeLat)) {
|
||||||
|
showToast('请输入止点桩纬度');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (isEmpty(formData.value.event?.occurLocation)) {
|
if (isEmpty(formData.value.event?.occurLocation)) {
|
||||||
showToast('请输入发生地点');
|
showToast('请输入发生地点');
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
<van-field v-model="formData.event.damageCount" label="水毁处数" placeholder="请填写" type="number" />
|
<van-field v-model="formData.event.damageCount" label="水毁处数" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 阻断里程 (event.blockedMileage) -->
|
<!-- 阻断里程 (event.blockedMileage) -->
|
||||||
<van-field v-model="formData.event.blockedMileage" label="阻断里程" placeholder="请填写" type="digit">
|
<van-field v-model="formData.event.blockedMileage" label="阻断里程" placeholder="请填写" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">公里</span>
|
<span class="field-unit">公里</span>
|
||||||
</template>
|
</template>
|
||||||
@ -30,25 +30,25 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 线路编号 (顶层 routeNo) -->
|
<!-- 线路编号 (顶层 routeNo) -->
|
||||||
<RoadRoutesPicker v-model="formData.event.routeNo" label="线路编号" placeholder="请线路" @change="handleRouteNoChange" />
|
<RoadRoutesPicker v-model="formData.event.routeNo" label="线路编号" placeholder="请选择" @change="handleRouteNoChange" />
|
||||||
|
|
||||||
<!-- 起点桩号 (event.startStakeNo) -->
|
<!-- 起点桩号 (event.startStakeNo) -->
|
||||||
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
|
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 起点桩经度 -->
|
<!-- 起点桩经度 -->
|
||||||
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 起点桩纬度 -->
|
<!-- 起点桩纬度 -->
|
||||||
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 止点桩号 (event.endStakeNo) -->
|
<!-- 止点桩号 (event.endStakeNo) -->
|
||||||
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
|
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 止点桩经度 -->
|
<!-- 止点桩经度 -->
|
||||||
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 止点桩纬度 -->
|
<!-- 止点桩纬度 -->
|
||||||
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="digit" />
|
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="number" />
|
||||||
|
|
||||||
<!-- 路况位置 (occurLocation) -->
|
<!-- 路况位置 (occurLocation) -->
|
||||||
<van-field v-model="formData.event.occurLocation" label="路况位置" placeholder="请填写" />
|
<van-field v-model="formData.event.occurLocation" label="路况位置" placeholder="请填写" />
|
||||||
@ -60,50 +60,51 @@
|
|||||||
|
|
||||||
<!-- 处置情况 (report) -->
|
<!-- 处置情况 (report) -->
|
||||||
<PanelItem title="处置情况">
|
<PanelItem title="处置情况">
|
||||||
<div class="disposal-measures">
|
<van-field label="处置措施" label-align="top">
|
||||||
<span class="measures-label">处置措施</span>
|
<template #input>
|
||||||
<div class="measures-options">
|
<div class="measures-options">
|
||||||
<van-row gutter="10">
|
<van-row gutter="10">
|
||||||
<van-col v-for="(item, index) in options['disposalMeasures']" :span="24 / options['disposalMeasures'].length" :key="index">
|
<van-col v-for="(item, index) in options['disposalMeasures']" :span="24 / options['disposalMeasures'].length" :key="index">
|
||||||
<van-button block plain :type="item.value === formData.report.disposalMeasures ? 'primary' : 'default'" @click="formData.report.disposalMeasures = item.value">
|
<van-button block plain :type="item.value === formData.report.disposalMeasures ? 'primary' : 'default'" @click="formData.report.disposalMeasures = item.value">
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</van-button>
|
</van-button>
|
||||||
</van-col>
|
</van-col>
|
||||||
</van-row>
|
</van-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</van-field>
|
||||||
|
|
||||||
<!-- 预计恢复时间 (report.expectRecoverTime) -->
|
<!-- 预计恢复时间 (report.expectRecoverTime) -->
|
||||||
<BaseDatePicker v-model="formData.report.expectRecoverTime" label="预计恢复时间" placeholder="请选择时间" :min-date="minDate" :max-date="maxDate" type="datetime" />
|
<BaseDatePicker v-model="formData.report.expectRecoverTime" label="预计恢复时间" placeholder="请选择时间" :min-date="minDate" :max-date="maxDate" type="datetime" />
|
||||||
|
|
||||||
<!-- 实际恢复时间 (report.actualRecoverTime) -->
|
<!-- 实际恢复时间 (report.actualRecoverTime) -->
|
||||||
<BaseDatePicker v-model="formData.report.actualRecoverTime" label="实际恢复时间" placeholder="请选择时间" :min-date="minDate" :max-date="maxDate" type="datetime" />
|
<BaseDatePicker v-model="formData.report.actualRecoverTime" label="实际恢复时间" placeholder="请选择时间(非必填)" :min-date="minDate" :max-date="maxDate" type="datetime" />
|
||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
<!-- 人员车辆 (report) -->
|
<!-- 人员车辆 (report) -->
|
||||||
<PanelItem title="人员车辆">
|
<PanelItem title="人员车辆">
|
||||||
<van-form>
|
<van-form>
|
||||||
<van-field v-model="formData.report.injuredCount" label="受伤人员" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.injuredCount" label="受伤人员" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">人</span>
|
<span class="field-unit">人</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.deadCount" label="死亡人员" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.deadCount" label="死亡人员" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">人</span>
|
<span class="field-unit">人</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.strandedPersonCount" label="滞留人员" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.strandedPersonCount" label="滞留人员" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">人</span>
|
<span class="field-unit">人</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.damagedVehicleCount" label="损坏车辆" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.damagedVehicleCount" label="损坏车辆" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">辆</span>
|
<span class="field-unit">辆</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.strandedVehicleCount" label="滞留车辆" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.strandedVehicleCount" label="滞留车辆" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">辆</span>
|
<span class="field-unit">辆</span>
|
||||||
</template>
|
</template>
|
||||||
@ -114,8 +115,8 @@
|
|||||||
<!-- 灾毁损失 (lossList) -->
|
<!-- 灾毁损失 (lossList) -->
|
||||||
<PanelItem title="灾毁损失">
|
<PanelItem title="灾毁损失">
|
||||||
<LossList v-model="formData.lossList" />
|
<LossList v-model="formData.lossList" />
|
||||||
<van-field v-model="formData.report.remark" label="处理情况" placeholder="请填写(选填)" />
|
<van-field v-model="formData.report.remark" label="处理情况" placeholder="请填写(非必填)" />
|
||||||
<van-field v-model="formData.report.totalLossAmount" label="损失总金额" placeholder="请填写(选填)" type="digit">
|
<van-field v-model="formData.report.totalLossAmount" label="损失总金额" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">万元</span>
|
<span class="field-unit">万元</span>
|
||||||
</template>
|
</template>
|
||||||
@ -124,22 +125,22 @@
|
|||||||
|
|
||||||
<!-- 投入资源 (report) -->
|
<!-- 投入资源 (report) -->
|
||||||
<PanelItem>
|
<PanelItem>
|
||||||
<van-field v-model="formData.report.investedMachinery" label="投入机械" placeholder="请填写" type="digit">
|
<van-field v-model="formData.report.investedMachinery" label="投入机械" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">台/班</span>
|
<span class="field-unit">台/班</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.investedManpower" label="投入人力" placeholder="请填写" type="number">
|
<van-field v-model="formData.report.investedManpower" label="投入人力" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">人次</span>
|
<span class="field-unit">人次</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.investedFunds" label="投入资金" placeholder="请填写" type="digit">
|
<van-field v-model="formData.report.investedFunds" label="投入资金" placeholder="请填写(非必填)" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">万元</span>
|
<span class="field-unit">万元</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
<van-field v-model="formData.report.siteDescription" label="现场描述" placeholder="请填写" type="textarea" rows="2" autosize />
|
<van-field v-model="formData.report.siteDescription" label="现场描述" placeholder="请填写(非必填)" type="textarea" rows="2" autosize />
|
||||||
<!-- 文件上传 -->
|
<!-- 文件上传 -->
|
||||||
<DisasterFileUpload label="附件上传" v-model="formData.fileList" />
|
<DisasterFileUpload label="附件上传" v-model="formData.fileList" />
|
||||||
</PanelItem>
|
</PanelItem>
|
||||||
@ -147,7 +148,7 @@
|
|||||||
<!-- 是否需要恢复重建 (event.needsRecovery) -->
|
<!-- 是否需要恢复重建 (event.needsRecovery) -->
|
||||||
<BasePicker v-model="formData.event.needsRecovery" :options="options['yesOrNoBool']" label="是否需要恢复重建" placeholder="请选择" />
|
<BasePicker v-model="formData.event.needsRecovery" :options="options['yesOrNoBool']" label="是否需要恢复重建" placeholder="请选择" />
|
||||||
<!-- 恢复重建预估费用 (event.estimatedRecoveryCost) -->
|
<!-- 恢复重建预估费用 (event.estimatedRecoveryCost) -->
|
||||||
<van-field v-model="formData.event.estimatedRecoveryCost" v-if="formData?.event.needsRecovery" label="恢复重建预估费用" placeholder="请填写" type="digit">
|
<van-field v-model="formData.event.estimatedRecoveryCost" v-if="formData?.event.needsRecovery" label="恢复重建预估费用" placeholder="请填写" type="number">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">万元</span>
|
<span class="field-unit">万元</span>
|
||||||
</template>
|
</template>
|
||||||
@ -310,10 +311,26 @@ const validate = () => {
|
|||||||
showToast('请输入起点桩号')
|
showToast('请输入起点桩号')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (isEmpty(formData.value.event?.startStakeLng)) {
|
||||||
|
showToast('请输入起点桩经度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.startStakeLat)) {
|
||||||
|
showToast('请输入起点桩纬度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (isEmpty(formData.value.event?.endStakeNo)) {
|
if (isEmpty(formData.value.event?.endStakeNo)) {
|
||||||
showToast('请输入止点桩号')
|
showToast('请输入止点桩号')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (isEmpty(formData.value.event?.endStakeLng)) {
|
||||||
|
showToast('请输入止点桩经度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.endStakeLat)) {
|
||||||
|
showToast('请输入止点桩纬度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (isEmpty(formData.value.event?.occurLocation)) {
|
if (isEmpty(formData.value.event?.occurLocation)) {
|
||||||
showToast('请输入路况位置')
|
showToast('请输入路况位置')
|
||||||
return false
|
return false
|
||||||
@ -533,7 +550,7 @@ defineExpose({
|
|||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.van-field__label) {
|
:deep(.van-field__label):not(.van-field__label--top) {
|
||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,12 +65,12 @@ const isValidImage = (file) => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const isLt500k = file.size / 1024 < 500
|
// const isLt500k = file.size / 1024 < 500
|
||||||
|
|
||||||
if (!isLt500k) {
|
// if (!isLt500k) {
|
||||||
showFailToast(`图片大小不能超过 500KB!当前大小:${(file.size / 1024).toFixed(2)}KB`)
|
// showFailToast(`图片大小不能超过 500KB!当前大小:${(file.size / 1024).toFixed(2)}KB`)
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,12 +63,10 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24">
|
<el-col :xs="24" :sm="24" :md="24" :lg="24">
|
||||||
<el-form-item>
|
<div class="filter-button">
|
||||||
<el-button type="primary" @click="handleQuery">查询</el-button>
|
<el-button type="primary" @click="toReport">新增填报</el-button>
|
||||||
<el-button @click="toReport">新增</el-button>
|
<el-button type="primary" color="#952DE6" @click="">导出</el-button>
|
||||||
<!-- <el-button type="success" @click="handleExport">导出Excel</el-button> -->
|
</div>
|
||||||
<el-button @click="resetFilters">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
@ -160,7 +158,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, reactive, onMounted, watch } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { request } from '@/utils/request'
|
import { request } from '@/utils/request'
|
||||||
@ -201,6 +199,10 @@ const pagination = reactive({
|
|||||||
total: 0
|
total: 0
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => filterForm, () => {
|
||||||
|
handleQuery()
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
const getDistrictName = (districtId) => {
|
const getDistrictName = (districtId) => {
|
||||||
if (!options.value.area?.length) return '-'
|
if (!options.value.area?.length) return '-'
|
||||||
return options.value.area.find((item) => item.value === districtId)?.label || '-'
|
return options.value.area.find((item) => item.value === districtId)?.label || '-'
|
||||||
@ -428,4 +430,9 @@ onMounted(() => {
|
|||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-button {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
<el-form :model="formData" v-if="formData.report">
|
<el-form :model="formData" v-if="formData.report">
|
||||||
<BlockItem title="处置情况">
|
<BlockItem title="处置情况">
|
||||||
<el-form-item label="处理措施">
|
<el-form-item label="处理措施" required>
|
||||||
<el-select v-model="formData.report.disposalMeasures" placeholder="请选择" style="width: 100%">
|
<el-select v-model="formData.report.disposalMeasures" placeholder="请选择" style="width: 100%">
|
||||||
<el-option v-for="(option, idx) in options['iceDisposalMeasures']" :key="idx" :label="option.label" :value="option.value" />
|
<el-option v-for="(option, idx) in options['iceDisposalMeasures']" :key="idx" :label="option.label" :value="option.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="预计恢复时间">
|
<el-form-item label="预计恢复时间" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="formData.report.expectRecoverTime"
|
v-model="formData.report.expectRecoverTime"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
@ -40,19 +40,19 @@
|
|||||||
|
|
||||||
<BlockItem title="实施情况">
|
<BlockItem title="实施情况">
|
||||||
<MaterialList v-model="formData.yhzMaterialList" :yhzId="formData.event.serviceStationId" :col-span="24" />
|
<MaterialList v-model="formData.yhzMaterialList" :yhzId="formData.event.serviceStationId" :col-span="24" />
|
||||||
<el-form-item label="投入资金">
|
<el-form-item label="投入资金" required>
|
||||||
<NumberInput v-model="formData.report.inputFunds" :precision="2" placeholder="请填写" style="width: 300px">
|
<NumberInput v-model="formData.report.inputFunds" :precision="2" placeholder="请填写" style="width: 300px">
|
||||||
<template #append>万元</template>
|
<template #append>万元</template>
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="投入人力">
|
<el-form-item label="投入人力" required>
|
||||||
<NumberInput v-model="formData.report.inputManpower" :precision="0" placeholder="请填写" style="width: 300px">
|
<NumberInput v-model="formData.report.inputManpower" :precision="0" placeholder="请填写" style="width: 300px">
|
||||||
<template #append>人次</template>
|
<template #append>人次</template>
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="投入设备">
|
<el-form-item label="投入设备" required>
|
||||||
<NumberInput v-model="formData.report.inputEquipment" :precision="1" placeholder="请填写" style="width: 300px">
|
<NumberInput v-model="formData.report.inputEquipment" :precision="1" placeholder="请填写" style="width: 300px">
|
||||||
<template #append>台/班</template>
|
<template #append>台/班</template>
|
||||||
</NumberInput>
|
</NumberInput>
|
||||||
@ -85,7 +85,6 @@
|
|||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleAddSubmit">追加记录</el-button>
|
<el-button type="primary" @click="handleAddSubmit">追加记录</el-button>
|
||||||
<el-button type="primary" @click="handleCompleteSubmit">解除事件</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -137,6 +136,18 @@ const validate = () => {
|
|||||||
ElMessage.warning('请选择预计恢复时间')
|
ElMessage.warning('请选择预计恢复时间')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if (form.report.inputFunds === null || form.report.inputFunds === undefined || form.report.inputFunds === '') {
|
||||||
|
ElMessage.warning('请填写投入资金')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (form.report.inputManpower === null || form.report.inputManpower === undefined || form.report.inputManpower === '') {
|
||||||
|
ElMessage.warning('请填写投入人力')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (form.report.inputEquipment === null || form.report.inputEquipment === undefined || form.report.inputEquipment === '') {
|
||||||
|
ElMessage.warning('请填写投入设备')
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (!form.report.siteDescription) {
|
if (!form.report.siteDescription) {
|
||||||
ElMessage.warning('请填写现场情况描述')
|
ElMessage.warning('请填写现场情况描述')
|
||||||
return false
|
return false
|
||||||
@ -182,15 +193,26 @@ const handleAddSubmit = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let apiUrl = '/snow-ops-platform/event/dispose'
|
||||||
|
if (formData.value.report?.disposalMeasures === '正常通行') {
|
||||||
|
apiUrl = '/snow-ops-platform/event/release'
|
||||||
|
}
|
||||||
|
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: '/snow-ops-platform/event/dispose',
|
url: apiUrl,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: getFormData()
|
data: getFormData()
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res?.code === '00000') {
|
if (res?.code === '00000') {
|
||||||
ElMessage.success('提交成功')
|
ElMessage.success('提交成功')
|
||||||
emit('refresh')
|
if (apiUrl === '/snow-ops-platform/event/release') {
|
||||||
|
setTimeout(() => {
|
||||||
|
router.replace({ path: '/iceDisasterDetail', query: { id: formData.value.event.id } })
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
emit('refresh')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res?.message || '提交失败')
|
ElMessage.error(res?.message || '提交失败')
|
||||||
}
|
}
|
||||||
@ -200,24 +222,6 @@ const handleAddSubmit = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCompleteSubmit = async () => {
|
|
||||||
const res = await request({
|
|
||||||
url: '/snow-ops-platform/event/release',
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
...formData.value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (res?.code === '00000') {
|
|
||||||
ElMessage.success('提交成功')
|
|
||||||
setTimeout(()=>{
|
|
||||||
router.replace({ path: '/iceDisasterDetail', query: { id: formData.value.event.id } })
|
|
||||||
}, 500)
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate,
|
validate,
|
||||||
initFormData,
|
initFormData,
|
||||||
|
|||||||
@ -82,11 +82,12 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="路况位置" prop="event.roadConditionLocation">
|
<el-form-item label="路况位置" prop="event.roadConditionLocation">
|
||||||
<el-input v-model="formData.event.roadConditionLocation" placeholder="请选择">
|
<PositionPickerDialog
|
||||||
<template #suffix>
|
v-model="formData.event.roadConditionLocation"
|
||||||
<el-icon class="location-icon"><LocationFilled /></el-icon>
|
:initial-longitude="formData.event.startStakeLng"
|
||||||
</template>
|
:initial-latitude="formData.event.startStakeLat"
|
||||||
</el-input>
|
@change="() => formRef?.validateField('event.roadConditionLocation')"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
@ -250,10 +251,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { LocationFilled } from '@element-plus/icons-vue'
|
|
||||||
import BlockItem from '@/component/BlockItem.vue'
|
import BlockItem from '@/component/BlockItem.vue'
|
||||||
import FileUpload from '@/component/FileUpload/FileUpload.vue'
|
import FileUpload from '@/component/FileUpload/FileUpload.vue'
|
||||||
import NumberInput from '@/component/NumberInput/NumberInput.vue'
|
import NumberInput from '@/component/NumberInput/NumberInput.vue'
|
||||||
|
import PositionPickerDialog from '../components/PositionPickerDialog.vue'
|
||||||
import RoadRoutesSelect from '../components/RoadRoutesSelect.vue'
|
import RoadRoutesSelect from '../components/RoadRoutesSelect.vue'
|
||||||
import YHZSelect from '../components/YHZSelect.vue'
|
import YHZSelect from '../components/YHZSelect.vue'
|
||||||
import MaterialList from '../components/MaterialList.vue'
|
import MaterialList from '../components/MaterialList.vue'
|
||||||
@ -321,10 +322,6 @@ const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.location-icon {
|
|
||||||
color: #909399;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-text {
|
.unit-text {
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export const useIceDisasterReport = () => {
|
|||||||
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
|
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
|
||||||
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
|
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
|
||||||
'event.occurLocation': [{ required: true, message: '请输入发生地点', trigger: 'blur' }],
|
'event.occurLocation': [{ required: true, message: '请输入发生地点', trigger: 'blur' }],
|
||||||
'event.roadConditionLocation': [{ required: true, message: '请输入路况位置', trigger: 'blur' }],
|
'event.roadConditionLocation': [{ required: true, message: '请选择路况位置', trigger: ['change', 'blur'] }],
|
||||||
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
|
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
|
||||||
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],
|
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],
|
||||||
'event.startStakeLat': [{ required: true, message: '请输入起点桩纬度', trigger: 'blur' }],
|
'event.startStakeLat': [{ required: true, message: '请输入起点桩纬度', trigger: 'blur' }],
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
<el-form :model="formData" >
|
<el-form :model="formData" >
|
||||||
<BlockItem title="处置情况">
|
<BlockItem title="处置情况">
|
||||||
<!-- 处置措施 -->
|
<!-- 处置措施 -->
|
||||||
<el-form-item label="处置措施">
|
<el-form-item label="处置措施" required>
|
||||||
<el-select v-model="formData.report.disposalMeasures">
|
<el-select v-model="formData.report.disposalMeasures">
|
||||||
<el-option label="半幅封闭" value="半幅封闭" />
|
<el-option label="半幅封闭" value="半幅封闭" />
|
||||||
<el-option label="全副封闭" value="全副封闭" />
|
<el-option label="全副封闭" value="全副封闭" />
|
||||||
@ -22,7 +22,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 预计恢复时间 -->
|
<!-- 预计恢复时间 -->
|
||||||
<el-form-item label="预计恢复时间">
|
<el-form-item label="预计恢复时间" required>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="formData.report.expectRecoverTime"
|
v-model="formData.report.expectRecoverTime"
|
||||||
type="datetime"
|
type="datetime"
|
||||||
@ -134,7 +134,6 @@
|
|||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleAddSubmit">追加记录</el-button>
|
<el-button type="primary" @click="handleAddSubmit">追加记录</el-button>
|
||||||
<el-button type="primary" @click="handleCompleteSubmit">解除事件</el-button>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -243,6 +242,14 @@ const calibrateTime = () => {
|
|||||||
|
|
||||||
// 表单验证
|
// 表单验证
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
|
if (!formData.value.report?.disposalMeasures) {
|
||||||
|
ElMessage.warning('请选择处理措施')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!formData.value.report?.expectRecoverTime) {
|
||||||
|
ElMessage.warning('请选择预计恢复时间')
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,16 +280,26 @@ const handleAddSubmit = async () => {
|
|||||||
// 可以在这里添加站点信息等其他数据
|
// 可以在这里添加站点信息等其他数据
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let apiUrl = '/snow-ops-platform/water-damage/dispose'
|
||||||
|
if (formData.value.report?.disposalMeasures === '正常通行') {
|
||||||
|
apiUrl = '/snow-ops-platform/water-damage/release'
|
||||||
|
}
|
||||||
|
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: '/snow-ops-platform/water-damage/dispose',
|
url: apiUrl,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: submitData
|
data: submitData
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res?.code === '00000') {
|
if (res?.code === '00000') {
|
||||||
ElMessage.success('提交成功')
|
ElMessage.success('提交成功')
|
||||||
|
if (apiUrl === '/snow-ops-platform/water-damage/release') {
|
||||||
emit('refresh')
|
setTimeout(() => {
|
||||||
|
router.replace({ path: '/waterDisasterDetail', query: { id: formData.value.event.id } })
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
emit('refresh')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message)
|
ElMessage.error(res.message)
|
||||||
}
|
}
|
||||||
@ -293,24 +310,6 @@ const handleAddSubmit = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCompleteSubmit = async () => {
|
|
||||||
const res = await request({
|
|
||||||
url: '/snow-ops-platform/water-damage/release',
|
|
||||||
method: 'post',
|
|
||||||
data: {
|
|
||||||
...formData.value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (res?.code === '00000') {
|
|
||||||
ElMessage.success('提交成功')
|
|
||||||
setTimeout(()=>{
|
|
||||||
router.replace({ path: '/waterDisasterDetail', query: { id: formData.value.event.id } })
|
|
||||||
}, 500)
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 暴露方法给父组件
|
// 暴露方法给父组件
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate,
|
validate,
|
||||||
|
|||||||
@ -118,11 +118,12 @@
|
|||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="路况位置" prop="event.occurLocation">
|
<el-form-item label="路况位置" prop="event.occurLocation">
|
||||||
<el-input v-model="formData.event.occurLocation" placeholder="请选择">
|
<PositionPickerDialog
|
||||||
<template #suffix>
|
v-model="formData.event.occurLocation"
|
||||||
<el-icon class="location-icon"><LocationFilled /></el-icon>
|
:initial-longitude="formData.event.startStakeLng"
|
||||||
</template>
|
:initial-latitude="formData.event.startStakeLat"
|
||||||
</el-input>
|
@change="() => formRef?.validateField('event.occurLocation')"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
@ -337,10 +338,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { LocationFilled } from '@element-plus/icons-vue'
|
|
||||||
import BlockItem from '@/component/BlockItem.vue'
|
import BlockItem from '@/component/BlockItem.vue'
|
||||||
import FileUpload from '@/component/FileUpload/FileUpload.vue'
|
import FileUpload from '@/component/FileUpload/FileUpload.vue'
|
||||||
import NumberInput from '@/component/NumberInput/NumberInput.vue'
|
import NumberInput from '@/component/NumberInput/NumberInput.vue'
|
||||||
|
import PositionPickerDialog from '../components/PositionPickerDialog.vue'
|
||||||
import RoadRoutesSelect from '../components/RoadRoutesSelect.vue'
|
import RoadRoutesSelect from '../components/RoadRoutesSelect.vue'
|
||||||
import YHZSelect from '../components/YHZSelect.vue'
|
import YHZSelect from '../components/YHZSelect.vue'
|
||||||
import LossList from './WaterDisasterLossListPC.vue'
|
import LossList from './WaterDisasterLossListPC.vue'
|
||||||
@ -409,10 +410,6 @@ const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.location-icon {
|
|
||||||
color: #909399;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-text {
|
.unit-text {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export const useWaterDisasterReport = () => {
|
|||||||
'event.damageCount': [{ required: true, message: '请输入水毁处数', trigger: 'blur' }],
|
'event.damageCount': [{ required: true, message: '请输入水毁处数', trigger: 'blur' }],
|
||||||
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
|
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
|
||||||
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
|
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
|
||||||
'event.occurLocation': [{ required: true, message: '请输入路况位置', trigger: 'blur' }],
|
'event.occurLocation': [{ required: true, message: '请选择路况位置', trigger: ['change', 'blur'] }],
|
||||||
'event.blockedPointName': [{ required: true, message: '请输入阻断点小地名', trigger: 'blur' }],
|
'event.blockedPointName': [{ required: true, message: '请输入阻断点小地名', trigger: 'blur' }],
|
||||||
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
|
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
|
||||||
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],
|
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],
|
||||||
|
|||||||
@ -0,0 +1,529 @@
|
|||||||
|
<template>
|
||||||
|
<div class="position-picker" @click="openDialog">
|
||||||
|
<el-input :model-value="modelValue" :placeholder="placeholder" readonly>
|
||||||
|
<template #suffix>
|
||||||
|
<el-icon class="trigger-icon"><LocationFilled /></el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="坐标点选取"
|
||||||
|
width="72%"
|
||||||
|
top="6vh"
|
||||||
|
class="position-dialog"
|
||||||
|
:append-to-body="true"
|
||||||
|
@opened="handleDialogOpened"
|
||||||
|
>
|
||||||
|
<div class="dialog-toolbar">
|
||||||
|
<div class="toolbar-item">
|
||||||
|
<span class="toolbar-label">经度:</span>
|
||||||
|
<el-input :model-value="displayLongitude" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="toolbar-item">
|
||||||
|
<span class="toolbar-label">纬度:</span>
|
||||||
|
<el-input :model-value="displayLatitude" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="toolbar-item toolbar-item--address">
|
||||||
|
<span class="toolbar-label">地点:</span>
|
||||||
|
<el-input v-model="searchKeyword" placeholder="请输入地点名称" @keyup.enter="handleSearch" />
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" :loading="searching" @click.stop="handleSearch">搜索</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="map-panel">
|
||||||
|
<div ref="mapContainerRef" class="map-container"></div>
|
||||||
|
<div v-if="mapError" class="map-state map-state--error">
|
||||||
|
<p>{{ mapError }}</p>
|
||||||
|
<el-button type="primary" plain @click="retryMapLoad">重新加载</el-button>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="!leafletReady" class="map-state">地图加载中...</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dialog-tip">支持地图点击选点和地点搜索,确定后会回填到路况位置。</div>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
|
||||||
|
import axios from 'axios'
|
||||||
|
import L from 'leaflet'
|
||||||
|
import 'leaflet/dist/leaflet.css'
|
||||||
|
import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png'
|
||||||
|
import markerIcon from 'leaflet/dist/images/marker-icon.png'
|
||||||
|
import markerShadow from 'leaflet/dist/images/marker-shadow.png'
|
||||||
|
import { LocationFilled } from '@element-plus/icons-vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { AMAP_CONFIG, AMAP_ENDPOINTS } from '../../3DSituationalAwarenessRefactor/config/amap'
|
||||||
|
|
||||||
|
const DEFAULT_CENTER = {
|
||||||
|
longitude: 106.551643,
|
||||||
|
latitude: 29.563761
|
||||||
|
}
|
||||||
|
|
||||||
|
delete L.Icon.Default.prototype._getIconUrl
|
||||||
|
L.Icon.Default.mergeOptions({
|
||||||
|
iconRetinaUrl: markerIcon2x,
|
||||||
|
iconUrl: markerIcon,
|
||||||
|
shadowUrl: markerShadow
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请选择'
|
||||||
|
},
|
||||||
|
initialLongitude: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
initialLatitude: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const leafletReady = ref(false)
|
||||||
|
const mapError = ref('')
|
||||||
|
const searching = ref(false)
|
||||||
|
const searchKeyword = ref('')
|
||||||
|
const mapContainerRef = ref(null)
|
||||||
|
|
||||||
|
const selectedLongitude = ref(null)
|
||||||
|
const selectedLatitude = ref(null)
|
||||||
|
const selectedAddress = ref('')
|
||||||
|
|
||||||
|
const draftLongitude = ref(null)
|
||||||
|
const draftLatitude = ref(null)
|
||||||
|
const draftAddress = ref('')
|
||||||
|
|
||||||
|
let mapInstance = null
|
||||||
|
let markerInstance = null
|
||||||
|
let reverseGeocodeToken = 0
|
||||||
|
|
||||||
|
const normalizeCoordinate = (value) => {
|
||||||
|
if (value === '' || value === null || value === undefined) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = Number(value)
|
||||||
|
return Number.isFinite(normalized) ? normalized : null
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayLongitude = computed(() => {
|
||||||
|
return draftLongitude.value === null ? '' : draftLongitude.value.toFixed(6)
|
||||||
|
})
|
||||||
|
|
||||||
|
const displayLatitude = computed(() => {
|
||||||
|
return draftLatitude.value === null ? '' : draftLatitude.value.toFixed(6)
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentCenter = () => {
|
||||||
|
const longitude = selectedLongitude.value ?? normalizeCoordinate(props.initialLongitude) ?? DEFAULT_CENTER.longitude
|
||||||
|
const latitude = selectedLatitude.value ?? normalizeCoordinate(props.initialLatitude) ?? DEFAULT_CENTER.latitude
|
||||||
|
|
||||||
|
return {
|
||||||
|
longitude,
|
||||||
|
latitude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveInitialSelection = () => {
|
||||||
|
if (selectedLongitude.value !== null && selectedLatitude.value !== null) {
|
||||||
|
return {
|
||||||
|
longitude: selectedLongitude.value,
|
||||||
|
latitude: selectedLatitude.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const longitude = normalizeCoordinate(props.initialLongitude)
|
||||||
|
const latitude = normalizeCoordinate(props.initialLatitude)
|
||||||
|
if (longitude !== null && latitude !== null) {
|
||||||
|
return {
|
||||||
|
longitude,
|
||||||
|
latitude
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const syncDraftFromSelected = () => {
|
||||||
|
const initialSelection = resolveInitialSelection()
|
||||||
|
draftLongitude.value = initialSelection?.longitude ?? null
|
||||||
|
draftLatitude.value = initialSelection?.latitude ?? null
|
||||||
|
draftAddress.value = selectedAddress.value || props.modelValue || ''
|
||||||
|
searchKeyword.value = draftAddress.value
|
||||||
|
}
|
||||||
|
|
||||||
|
const setMarkerPosition = (longitude, latitude, shouldPan = true) => {
|
||||||
|
if (!mapInstance || longitude === null || latitude === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const latLng = [latitude, longitude]
|
||||||
|
if (!markerInstance) {
|
||||||
|
markerInstance = L.marker(latLng, {
|
||||||
|
draggable: true
|
||||||
|
}).addTo(mapInstance)
|
||||||
|
|
||||||
|
markerInstance.on('dragend', () => {
|
||||||
|
const markerLatLng = markerInstance.getLatLng()
|
||||||
|
updateDraftPosition(markerLatLng.lng, markerLatLng.lat, true)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
markerInstance.setLatLng(latLng)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldPan) {
|
||||||
|
mapInstance.setView(latLng, Math.max(mapInstance.getZoom(), 15))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const reverseGeocode = async (longitude, latitude) => {
|
||||||
|
const token = ++reverseGeocodeToken
|
||||||
|
const url = `${AMAP_CONFIG.baseUrl}${AMAP_ENDPOINTS.regeocode}`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.get(url, {
|
||||||
|
params: {
|
||||||
|
key: AMAP_CONFIG.webServiceKey,
|
||||||
|
location: `${longitude},${latitude}`,
|
||||||
|
extensions: 'base',
|
||||||
|
output: 'json'
|
||||||
|
},
|
||||||
|
timeout: AMAP_CONFIG.timeout
|
||||||
|
})
|
||||||
|
|
||||||
|
if (token !== reverseGeocodeToken) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.data.status !== '1') {
|
||||||
|
throw new Error(response.data.info || '逆地理编码失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedAddress = response.data.regeocode?.formatted_address || ''
|
||||||
|
draftAddress.value = formattedAddress
|
||||||
|
searchKeyword.value = formattedAddress
|
||||||
|
} catch (_error) {
|
||||||
|
if (token !== reverseGeocodeToken) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
draftAddress.value = draftAddress.value || `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateDraftPosition = (longitude, latitude, shouldResolveAddress = false) => {
|
||||||
|
draftLongitude.value = Number(longitude.toFixed(6))
|
||||||
|
draftLatitude.value = Number(latitude.toFixed(6))
|
||||||
|
setMarkerPosition(draftLongitude.value, draftLatitude.value, false)
|
||||||
|
|
||||||
|
if (shouldResolveAddress) {
|
||||||
|
reverseGeocode(draftLongitude.value, draftLatitude.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const initMap = async () => {
|
||||||
|
mapError.value = ''
|
||||||
|
leafletReady.value = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
await nextTick()
|
||||||
|
|
||||||
|
if (!mapContainerRef.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const center = currentCenter()
|
||||||
|
|
||||||
|
if (!mapInstance) {
|
||||||
|
mapInstance = L.map(mapContainerRef.value, {
|
||||||
|
zoomControl: true,
|
||||||
|
attributionControl: false
|
||||||
|
}).setView([center.latitude, center.longitude], 13)
|
||||||
|
|
||||||
|
L.tileLayer('https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', {
|
||||||
|
subdomains: ['1', '2', '3', '4'],
|
||||||
|
maxZoom: 18,
|
||||||
|
minZoom: 3
|
||||||
|
}).addTo(mapInstance)
|
||||||
|
|
||||||
|
mapInstance.on('click', (event) => {
|
||||||
|
updateDraftPosition(event.latlng.lng, event.latlng.lat, true)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
mapInstance.setView([center.latitude, center.longitude], mapInstance.getZoom() || 13)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draftLongitude.value !== null && draftLatitude.value !== null) {
|
||||||
|
setMarkerPosition(draftLongitude.value, draftLatitude.value)
|
||||||
|
} else if (markerInstance) {
|
||||||
|
markerInstance.remove()
|
||||||
|
markerInstance = null
|
||||||
|
}
|
||||||
|
leafletReady.value = true
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
mapInstance?.invalidateSize()
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!draftAddress.value && draftLongitude.value !== null && draftLatitude.value !== null) {
|
||||||
|
reverseGeocode(draftLongitude.value, draftLatitude.value)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('地图初始化失败:', error)
|
||||||
|
mapError.value = '地图初始化失败,请检查网络后重试'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDialog = () => {
|
||||||
|
syncDraftFromSelected()
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogOpened = async () => {
|
||||||
|
await initMap()
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
mapInstance?.invalidateSize()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = async () => {
|
||||||
|
const keyword = searchKeyword.value.trim()
|
||||||
|
if (!keyword) {
|
||||||
|
ElMessage.warning('请输入地点名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
searching.value = true
|
||||||
|
try {
|
||||||
|
const url = `${AMAP_CONFIG.baseUrl}${AMAP_ENDPOINTS.geocode}`
|
||||||
|
const response = await axios.get(url, {
|
||||||
|
params: {
|
||||||
|
key: AMAP_CONFIG.webServiceKey,
|
||||||
|
address: keyword,
|
||||||
|
output: 'json'
|
||||||
|
},
|
||||||
|
timeout: AMAP_CONFIG.timeout
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response.data.status !== '1') {
|
||||||
|
throw new Error(response.data.info || '地点搜索失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const geocode = response.data.geocodes?.[0]
|
||||||
|
if (!geocode?.location) {
|
||||||
|
throw new Error('未找到对应地点')
|
||||||
|
}
|
||||||
|
|
||||||
|
const [longitude, latitude] = geocode.location.split(',').map(Number)
|
||||||
|
draftAddress.value = geocode.formatted_address || keyword
|
||||||
|
searchKeyword.value = draftAddress.value
|
||||||
|
updateDraftPosition(longitude, latitude)
|
||||||
|
setMarkerPosition(longitude, latitude)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('地点搜索失败:', error)
|
||||||
|
ElMessage.error(error.message || '地点搜索失败,请重试')
|
||||||
|
} finally {
|
||||||
|
searching.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const retryMapLoad = () => {
|
||||||
|
initMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
if (draftLongitude.value === null || draftLatitude.value === null) {
|
||||||
|
ElMessage.warning('请先选择坐标点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedLongitude.value = draftLongitude.value
|
||||||
|
selectedLatitude.value = draftLatitude.value
|
||||||
|
selectedAddress.value = draftAddress.value || searchKeyword.value.trim() || `${draftLatitude.value}, ${draftLongitude.value}`
|
||||||
|
|
||||||
|
emit('update:modelValue', selectedAddress.value)
|
||||||
|
emit('change', {
|
||||||
|
longitude: selectedLongitude.value,
|
||||||
|
latitude: selectedLatitude.value,
|
||||||
|
address: selectedAddress.value
|
||||||
|
})
|
||||||
|
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(value) => {
|
||||||
|
if (!value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedAddress.value = value
|
||||||
|
if (!dialogVisible.value) {
|
||||||
|
draftAddress.value = value
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (mapInstance) {
|
||||||
|
mapInstance.remove()
|
||||||
|
mapInstance = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.position-picker {
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
:deep(.el-input__wrapper) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input__inner) {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigger-icon {
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-toolbar {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr) auto;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-item--address {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar-label {
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-panel {
|
||||||
|
position: relative;
|
||||||
|
height: min(600px, calc(100vh - 290px));
|
||||||
|
min-height: 320px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-state {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
background: rgba(245, 247, 250, 0.92);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-state--error {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-tip {
|
||||||
|
margin-top: 12px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.leaflet-container) {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.leaflet-control-zoom a) {
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.position-dialog) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.position-dialog .el-dialog) {
|
||||||
|
max-height: 88vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.position-dialog .el-dialog__body) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-height: 900px) {
|
||||||
|
.map-panel {
|
||||||
|
height: calc(100vh - 320px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1280px) {
|
||||||
|
.dialog-toolbar {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.dialog-toolbar {
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-panel {
|
||||||
|
height: calc(100vh - 400px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -50,8 +50,8 @@ export function useOptions() {
|
|||||||
options.value['disposalMeasures'] = [
|
options.value['disposalMeasures'] = [
|
||||||
{ label: '全幅封闭', value: '全幅封闭' },
|
{ label: '全幅封闭', value: '全幅封闭' },
|
||||||
{ label: '半幅封闭', value: '半幅封闭' },
|
{ label: '半幅封闭', value: '半幅封闭' },
|
||||||
{ label: '正常通行', value: '正常通行' },
|
{ label: '便道通行', value: '便道通行' },
|
||||||
{ label: '限制通行', value: '限制通行' }
|
{ label: '正常通行', value: '正常通行' }
|
||||||
]
|
]
|
||||||
|
|
||||||
// 冰灾 处理措施
|
// 冰灾 处理措施
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user