feat: h5灾毁管理
This commit is contained in:
parent
3af90b27da
commit
4832facbf9
@ -15,6 +15,7 @@
|
|||||||
<!-- 弹出层选择器 -->
|
<!-- 弹出层选择器 -->
|
||||||
<van-popup v-model:show="showPicker" position="bottom" round>
|
<van-popup v-model:show="showPicker" position="bottom" round>
|
||||||
<van-picker
|
<van-picker
|
||||||
|
:modelValue="getPickerValue()"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:title="pickerTitle"
|
:title="pickerTitle"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@ -91,12 +92,32 @@ const emit = defineEmits(['update:modelValue', 'change'])
|
|||||||
// 控制弹出层显示
|
// 控制弹出层显示
|
||||||
const showPicker = ref(false)
|
const showPicker = ref(false)
|
||||||
|
|
||||||
|
const getPickerValue = () => {
|
||||||
|
// 布尔值需要转换为数字交给picker, 在设置的时候,又需要转换回来
|
||||||
|
if(props.modelValue === true) return [1]
|
||||||
|
if(props.modelValue === false) return [0]
|
||||||
|
return [props.modelValue]
|
||||||
|
}
|
||||||
|
|
||||||
// 处理 Picker 数据格式:将 options 转为 Picker 需要的文本数组
|
// 处理 Picker 数据格式:将 options 转为 Picker 需要的文本数组
|
||||||
const columns = computed(() => {
|
const columns = computed(() => {
|
||||||
return props.options.map(item => {
|
return props.options.map(item => {
|
||||||
|
let value = item[props.valueKey]
|
||||||
|
let isBoolean = false
|
||||||
|
// vant不支持布尔值,需要做转换
|
||||||
|
if(value === true) {
|
||||||
|
value = 1
|
||||||
|
isBoolean = true
|
||||||
|
}
|
||||||
|
if(value === false) {
|
||||||
|
value = 0
|
||||||
|
isBoolean = true
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: item[props.labelKey],
|
text: item[props.labelKey],
|
||||||
value: item[props.valueKey]
|
value,
|
||||||
|
isBoolean
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -119,7 +140,11 @@ const openPicker = () => {
|
|||||||
|
|
||||||
// 确认选择
|
// 确认选择
|
||||||
const onConfirm = ({ selectedValues, selectedOptions }) => {
|
const onConfirm = ({ selectedValues, selectedOptions }) => {
|
||||||
const value = selectedOptions[0][props.valueKey]
|
let value = selectedOptions[0][props.valueKey]
|
||||||
|
// 如果是布尔值,需要转换为布尔值
|
||||||
|
if(selectedOptions[0].isBoolean) {
|
||||||
|
value = value === 1 ? true : false
|
||||||
|
}
|
||||||
const label = selectedOptions[0][props.labelKey]
|
const label = selectedOptions[0][props.labelKey]
|
||||||
emit('update:modelValue', value)
|
emit('update:modelValue', value)
|
||||||
emit('change', { value, label })
|
emit('change', { value, label })
|
||||||
|
|||||||
@ -45,17 +45,7 @@ const props = defineProps({
|
|||||||
// 标签列表
|
// 标签列表
|
||||||
tags: {
|
tags: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [
|
default: () => []
|
||||||
{ label: '全部', value: 'all' },
|
|
||||||
{ label: '边坡坍塌', value: '边坡坍塌' },
|
|
||||||
{ label: '泥石流', value: '泥石流' },
|
|
||||||
{ label: '路基沉陷', value: '路基沉陷' },
|
|
||||||
{ label: '山体滑坡', value: '山体滑坡' },
|
|
||||||
{ label: '行道树倒塌', value: '行道树倒塌' },
|
|
||||||
{ label: '积水', value: '积水' },
|
|
||||||
{ label: '积雪', value: '积雪' },
|
|
||||||
{ label: '其他', value: '其他' }
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -86,7 +76,8 @@ const selectTag = (value) => {
|
|||||||
|
|
||||||
// 重置筛选
|
// 重置筛选
|
||||||
const resetFilter = () => {
|
const resetFilter = () => {
|
||||||
tempSelectedTag.value = 'all'
|
tempSelectedTag.value = null
|
||||||
|
emit('update:modelValue', tempSelectedTag.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确认筛选
|
// 确认筛选
|
||||||
|
|||||||
@ -62,7 +62,7 @@ const routes = [
|
|||||||
component: () => import('../views/IceEvent/IceEventAdd.vue')
|
component: () => import('../views/IceEvent/IceEventAdd.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/iceEventDetail/:data',
|
path: '/iceEventDetail',
|
||||||
name: 'IceEventDetail',
|
name: 'IceEventDetail',
|
||||||
component: () => import('../views/IceEvent/IceEventDetails.vue')
|
component: () => import('../views/IceEvent/IceEventDetails.vue')
|
||||||
},
|
},
|
||||||
@ -107,9 +107,8 @@ const routes = [
|
|||||||
component: () => import('../views/DisasterManagement/DisasterReport.vue')
|
component: () => import('../views/DisasterManagement/DisasterReport.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/disasterDetail',
|
path: '/waterDisasterDetail',
|
||||||
name: 'DisasterDetail',
|
component: () => import('../views/DisasterManagement/WaterDisasterDetail.vue')
|
||||||
component: () => import('../views/DisasterManagement/DisasterDetail.vue')
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageContainer title="灾害管理" @click-back="handleClickBack">
|
<PageContainer title="灾害管理" @click-back="handleClickBack">
|
||||||
|
<div class="filter-wrapper">
|
||||||
|
<SearchInput style="margin-top: 0" v-model="searchValue" placeholder="请输入地点关键词" @search="handleSearch" />
|
||||||
|
<div class="filter-btn-block">
|
||||||
|
<van-button @click="showFilter = true">
|
||||||
|
<div class="filter-btn">
|
||||||
|
<span style="white-space: nowrap">{{ getShortTypeName(selectedDisasterType) }}</span> <van-icon name="filter-o" />
|
||||||
|
</div>
|
||||||
|
</van-button>
|
||||||
|
</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)">
|
<CardItem v-for="(item, index) in list" :key="index" :title="getEventTitle(item)" @click="handleClickItem(item)">
|
||||||
<template #headerExtra>
|
<template #headerExtra>
|
||||||
@ -37,18 +46,13 @@
|
|||||||
<van-button type="primary" class="footer-btn" @click="handleAdd">灾害填报</van-button>
|
<van-button type="primary" class="footer-btn" @click="handleAdd">灾害填报</van-button>
|
||||||
|
|
||||||
<!-- 筛选组件:v-model 绑定选中的值,visible 控制显示隐藏 -->
|
<!-- 筛选组件:v-model 绑定选中的值,visible 控制显示隐藏 -->
|
||||||
<TagFilter
|
<TagFilter v-model="selectedDisasterType" :visible="showFilter" :tags="disasterTypes" @update:visible="showFilter = $event" @confirm="handleFilterConfirm" />
|
||||||
v-model="selectedDisasterType"
|
|
||||||
:visible="showFilter"
|
|
||||||
@update:visible="showFilter = $event"
|
|
||||||
@confirm="handleFilterConfirm"
|
|
||||||
/>
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { RouterLink, 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, Loading as VanLoading, Icon as VanIcon, Button as VanButton, showImagePreview } 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'
|
||||||
@ -56,7 +60,7 @@ import CardItem from '@/components/CardItem.vue'
|
|||||||
import EmptyBox from '@/components/EmptyBox.vue'
|
import EmptyBox from '@/components/EmptyBox.vue'
|
||||||
import CurrentSite from '@/components/CurrentSite.vue'
|
import CurrentSite from '@/components/CurrentSite.vue'
|
||||||
import TagFilter from '@/components/TagFilter.vue'
|
import TagFilter from '@/components/TagFilter.vue'
|
||||||
import { request } from "@shared/utils/request";
|
import { request } from '@shared/utils/request'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@ -76,11 +80,11 @@ const emptyText = ref('暂无相关灾毁信息')
|
|||||||
const showFilter = ref(false)
|
const showFilter = ref(false)
|
||||||
|
|
||||||
// 当前选中的灾毁类型(通过 v-model 传给 TagFilter)
|
// 当前选中的灾毁类型(通过 v-model 传给 TagFilter)
|
||||||
const selectedDisasterType = ref('all')
|
const selectedDisasterType = ref(null)
|
||||||
|
|
||||||
// 灾毁类型列表(根据实际数据中的路况类别或其他字段定义)
|
// 灾毁类型列表(根据实际数据中的路况类别或其他字段定义)
|
||||||
const disasterTypes = [
|
const disasterTypes = [
|
||||||
{ label: '全部', value: 'all' },
|
{ label: '全部', value: null },
|
||||||
{ label: '边坡坍塌', value: '边坡坍塌' },
|
{ label: '边坡坍塌', value: '边坡坍塌' },
|
||||||
{ label: '泥石流', value: '泥石流' },
|
{ label: '泥石流', value: '泥石流' },
|
||||||
{ label: '路基沉陷', value: '路基沉陷' },
|
{ label: '路基沉陷', value: '路基沉陷' },
|
||||||
@ -93,17 +97,14 @@ const disasterTypes = [
|
|||||||
|
|
||||||
// 获取事件标题
|
// 获取事件标题
|
||||||
const getEventTitle = (item) => {
|
const getEventTitle = (item) => {
|
||||||
// 优先使用 eventName,其次使用发生地点+线路编号组合
|
|
||||||
if (item.eventName) {
|
|
||||||
return item.eventName
|
|
||||||
}
|
|
||||||
const parts = []
|
const parts = []
|
||||||
if (item.routeNo) parts.push(item.routeNo)
|
|
||||||
if (item.occurLocation) parts.push(item.occurLocation)
|
if (item.occurLocation) parts.push(item.occurLocation)
|
||||||
if (item.startStakeNo) parts.push(item.startStakeNo)
|
if (item.routeNo) parts.push(item.routeNo)
|
||||||
|
// if(item.disasterType) parts.push(item.disasterType == 'WATER_DAMAGE' ? '发生水毁灾害' : '发生冰雪灾害')
|
||||||
|
if (item.roadConditionType) parts.push('发生' + item.roadConditionType)
|
||||||
|
|
||||||
if (parts.length > 0) {
|
if (parts.length > 0) {
|
||||||
return parts.join(' ')
|
return parts.join('')
|
||||||
}
|
}
|
||||||
return '未命名事件'
|
return '未命名事件'
|
||||||
}
|
}
|
||||||
@ -121,72 +122,59 @@ const getEventStatusType = (status) => {
|
|||||||
|
|
||||||
// 获取灾毁类型文本(根据实际情况映射)
|
// 获取灾毁类型文本(根据实际情况映射)
|
||||||
const getDisasterTypeText = (item) => {
|
const getDisasterTypeText = (item) => {
|
||||||
// 可以根据 roadConditionType、repairProgress 或其他字段来生成类型标签
|
|
||||||
// 这里提供几种可能的映射方式
|
|
||||||
|
|
||||||
// 方式1:根据抢险进度
|
|
||||||
if (item.repairProgress) {
|
|
||||||
return item.repairProgress
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方式2:根据路况类别
|
|
||||||
if (item.roadConditionType) {
|
if (item.roadConditionType) {
|
||||||
return item.roadConditionType
|
return item.roadConditionType
|
||||||
}
|
}
|
||||||
|
|
||||||
// 方式3:默认返回"水毁灾害"
|
|
||||||
return '水毁灾害'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取简短类型名称
|
// 获取简短类型名称
|
||||||
const getShortTypeName = (type) => {
|
const getShortTypeName = (type) => {
|
||||||
const typeMap = {
|
const typeMap = {
|
||||||
'边坡坍塌': '边坡',
|
边坡坍塌: '边坡',
|
||||||
'泥石流': '泥石',
|
泥石流: '泥石',
|
||||||
'路基沉陷': '路基',
|
路基沉陷: '路基',
|
||||||
'山体滑坡': '滑坡',
|
山体滑坡: '滑坡',
|
||||||
'行道树倒塌': '树倒',
|
行道树倒塌: '树倒',
|
||||||
'积水': '积水',
|
积水: '积水',
|
||||||
'积雪': '积雪',
|
积雪: '积雪',
|
||||||
'其他': '其他',
|
其他: '其他',
|
||||||
'未抢险': '待抢险',
|
未抢险: '待抢险',
|
||||||
'抢险中': '抢险中',
|
抢险中: '抢险中',
|
||||||
'已完成': '已完成',
|
已完成: '已完成',
|
||||||
'高速公路': '高速',
|
高速公路: '高速',
|
||||||
'国道': '国道',
|
国道: '国道',
|
||||||
'省道': '省道'
|
省道: '省道'
|
||||||
}
|
}
|
||||||
return typeMap[type] || (type ? type.substring(0, 2) : '灾害')
|
return typeMap[type] || (type ? type.substring(0, 2) : '全部')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取灾毁列表数据
|
// 获取灾毁列表数据
|
||||||
const getDisasterList = async (keyword = '', disasterType = 'all') => {
|
const getDisasterList = async (keyword = '', disasterType = null) => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await request({
|
const result = await request({
|
||||||
url: '/snow-ops-platform/water-damage/list',
|
url: '/snow-ops-platform/unified-disaster/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
|
pageSize: 999,
|
||||||
keyword: keyword.trim(),
|
keyword: keyword.trim(),
|
||||||
disasterType: disasterType === 'all' ? '' : disasterType
|
roadConditionType: disasterType || undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (result?.data?.records) {
|
if (result?.data?.records) {
|
||||||
list.value = result.data.records.map(item => ({
|
list.value = result.data.records.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
// 数据转换,确保前端使用的字段存在
|
// 数据转换,确保前端使用的字段存在
|
||||||
title: getEventTitle(item),
|
title: getEventTitle(item),
|
||||||
status: getEventStatusText(item.eventStatus),
|
status: getEventStatusText(item.eventStatus),
|
||||||
occurTime: item.occurTime,
|
occurTime: item.occurTime,
|
||||||
estimateRecoverTime: item.expectRecoverTime,
|
estimateRecoverTime: item.expectRecoverTime
|
||||||
disasterType: getDisasterTypeText(item)
|
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
showToast(result.message || '获取数据失败')
|
showToast(result.message || '获取数据失败')
|
||||||
list.value = []
|
list.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取灾毁列表失败:', error)
|
console.error('获取灾毁列表失败:', error)
|
||||||
showToast('获取数据失败,请稍后重试')
|
showToast('获取数据失败,请稍后重试')
|
||||||
@ -201,14 +189,6 @@ const handleSearch = () => {
|
|||||||
getDisasterList(searchValue.value, selectedDisasterType.value)
|
getDisasterList(searchValue.value, selectedDisasterType.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击全部按钮
|
|
||||||
const handleAllClick = () => {
|
|
||||||
if (selectedDisasterType.value !== 'all') {
|
|
||||||
selectedDisasterType.value = 'all'
|
|
||||||
getDisasterList(searchValue.value, 'all')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 筛选确认
|
// 筛选确认
|
||||||
const handleFilterConfirm = (type) => {
|
const handleFilterConfirm = (type) => {
|
||||||
// selectedDisasterType 已经通过 v-model 更新,这里只需重新请求数据
|
// selectedDisasterType 已经通过 v-model 更新,这里只需重新请求数据
|
||||||
@ -222,12 +202,22 @@ const handleClickBack = () => {
|
|||||||
|
|
||||||
// 点击列表项
|
// 点击列表项
|
||||||
const handleClickItem = (item) => {
|
const handleClickItem = (item) => {
|
||||||
router.push({
|
if (item.disasterType === 'WATER_DAMAGE') {
|
||||||
path: '/disasterDetail',
|
router.push({
|
||||||
query: {
|
path: '/waterDisasterDetail',
|
||||||
id: item.id
|
query: {
|
||||||
}
|
id: item.id
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (item.disasterType === 'ICE_SNOW') {
|
||||||
|
router.push({
|
||||||
|
name: 'IceEventDetail',
|
||||||
|
query: {
|
||||||
|
id: item.relationId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 灾毁填报
|
// 灾毁填报
|
||||||
@ -249,6 +239,23 @@ onMounted(() => {
|
|||||||
padding-bottom: 80px;
|
padding-bottom: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
|
||||||
|
.filter-btn-block {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
.filter-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.card-item) {
|
:deep(.card-item) {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -330,4 +337,4 @@ onMounted(() => {
|
|||||||
:deep(.van-tag) {
|
:deep(.van-tag) {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -5,22 +5,16 @@
|
|||||||
|
|
||||||
<!-- 事件类型 -->
|
<!-- 事件类型 -->
|
||||||
<PanelItem title="事件类型" style="margin-bottom: 10px" v-if="!isContinue">
|
<PanelItem title="事件类型" style="margin-bottom: 10px" v-if="!isContinue">
|
||||||
<van-radio-group v-model="eventType" direction="horizontal" class="event-type-group">
|
<van-row gutter="10">
|
||||||
<van-radio name="water">水毁灾害</van-radio>
|
<van-col v-for="(item, index) in eventTypeOptions" :span="24 / eventTypeOptions.length" :key="index">
|
||||||
<van-radio name="ice">冰雪灾害</van-radio>
|
<van-button block plain :type="item.value === eventType ? 'primary' : 'default'" @click="eventType = item.value"> {{ item.label }} </van-button>
|
||||||
</van-radio-group>
|
</van-col>
|
||||||
|
</van-row>
|
||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
<!-- 根据事件类型渲染不同表单 -->
|
<!-- 根据事件类型渲染不同表单 -->
|
||||||
<WaterDisaster v-if="eventType === 'water'" ref="waterDisasterRef" />
|
<WaterDisaster v-if="eventType === 'water'" />
|
||||||
|
<IceDisaster v-if="eventType === 'ice'" />
|
||||||
<!-- 冰雪灾害表单(待实现) -->
|
|
||||||
<div v-else class="coming-soon">
|
|
||||||
<van-empty description="冰雪灾害表单开发中..." />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 提交按钮 -->
|
|
||||||
<van-button type="primary" class="footer-btn" @click="handleSubmit" :loading="submitting"> 提交 </van-button>
|
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -32,8 +26,8 @@ import PageContainer from '@/components/PageContainer.vue'
|
|||||||
import CurrentSite from '@/components/CurrentSite.vue'
|
import CurrentSite from '@/components/CurrentSite.vue'
|
||||||
import PanelItem from '@/components/PanelItem.vue'
|
import PanelItem from '@/components/PanelItem.vue'
|
||||||
import WaterDisaster from './WaterDisaster/WaterDisaster.vue'
|
import WaterDisaster from './WaterDisaster/WaterDisaster.vue'
|
||||||
|
import IceDisaster from './IceDisaster.vue'
|
||||||
import { request } from '@shared/utils/request'
|
import { request } from '@shared/utils/request'
|
||||||
import mockFormData from './waterDisasterFormData.json'
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@ -45,118 +39,27 @@ const title = ref(!isContinue ? '灾毁填报' : '灾毁续报')
|
|||||||
|
|
||||||
// 事件类型
|
// 事件类型
|
||||||
const eventType = ref('water')
|
const eventType = ref('water')
|
||||||
|
const eventTypeOptions = [
|
||||||
// 表单数据
|
{
|
||||||
const formData = ref(route.query.mock ? mockFormData : {})
|
label: '水毁灾害',
|
||||||
const waterDisasterRef = ref(null)
|
value: 'water'
|
||||||
const submitting = ref(false)
|
},
|
||||||
|
{
|
||||||
|
label: '冰雪灾害',
|
||||||
|
value: 'ice'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
// 返回上一页
|
// 返回上一页
|
||||||
const handleClickBack = () => {
|
const handleClickBack = () => {
|
||||||
router.replace('/disasterManagement')
|
router.replace('/disasterManagement')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交表单
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
// 验证表单
|
|
||||||
if (eventType.value === 'water') {
|
|
||||||
if (!waterDisasterRef.value.validate()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
submitting.value = true
|
|
||||||
try {
|
|
||||||
// 获取表单数据
|
|
||||||
let formData = {}
|
|
||||||
if (eventType.value === 'water') {
|
|
||||||
formData = waterDisasterRef.value.getFormData()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加事件类型和站点信息
|
|
||||||
const submitData = {
|
|
||||||
...formData
|
|
||||||
// 可以在这里添加站点信息等其他数据
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await request({
|
|
||||||
url: '/snow-ops-platform/water-damage/addOrUpdate',
|
|
||||||
method: 'post',
|
|
||||||
data: submitData
|
|
||||||
})
|
|
||||||
|
|
||||||
if (res?.code === '00000') {
|
|
||||||
showSuccessToast('提交成功')
|
|
||||||
if (submitData.event.needsRecovery) {
|
|
||||||
router.replace({
|
|
||||||
name: 'RebuildAdd',
|
|
||||||
params: {
|
|
||||||
data: res.data.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 提交成功后返回列表页
|
|
||||||
setTimeout(() => {
|
|
||||||
router.replace('/disasterManagement')
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showFailToast(res.message)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
showFailToast('提交失败,请重试')
|
|
||||||
console.error('提交失败:', error)
|
|
||||||
} finally {
|
|
||||||
submitting.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取灾毁详情
|
|
||||||
const getDisasterDetail = async () => {
|
|
||||||
const id = route.query.id
|
|
||||||
if (!id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await request({
|
|
||||||
url: `/snow-ops-platform/water-damage/getById`,
|
|
||||||
method: 'get',
|
|
||||||
params: { id }
|
|
||||||
})
|
|
||||||
|
|
||||||
if (result?.data) {
|
|
||||||
// 接口返回 Data 结构
|
|
||||||
const data = result.data
|
|
||||||
const newFormData = {
|
|
||||||
...data,
|
|
||||||
lossList: null,
|
|
||||||
report: formData.value.report,
|
|
||||||
fileList: null
|
|
||||||
}
|
|
||||||
waterDisasterRef.value.initFormData(newFormData)
|
|
||||||
} else {
|
|
||||||
showToast(result.message || '获取详情失败')
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取灾毁详情失败:', error)
|
|
||||||
showToast('获取详情失败,请稍后重试')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (route.query?.id) {
|
|
||||||
getDisasterDetail()
|
|
||||||
} else {
|
|
||||||
waterDisasterRef.value.initFormData(formData.value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.page-container {
|
.page-container {
|
||||||
padding-bottom: 80px;
|
|
||||||
background-color: #f5f7fa;
|
background-color: #f5f7fa;
|
||||||
|
padding-bottom: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-type-group {
|
.event-type-group {
|
||||||
@ -170,26 +73,4 @@ onMounted(() => {
|
|||||||
.coming-soon {
|
.coming-soon {
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-btn {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 15px;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
width: calc(100% - 32px);
|
|
||||||
max-width: 340px;
|
|
||||||
border-radius: 48px;
|
|
||||||
height: 48px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
opacity: 0.9;
|
|
||||||
transform: translateX(-50%) scale(0.98);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
524
packages/mobile/src/views/DisasterManagement/IceDisaster.vue
Normal file
524
packages/mobile/src/views/DisasterManagement/IceDisaster.vue
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home">
|
||||||
|
<div class="content">
|
||||||
|
<PanelItem title="基本信息">
|
||||||
|
<van-form class="IceEventAddForm" label-align="left" colon>
|
||||||
|
<van-field v-model="form.event.occurTime" label="发生时间" center>
|
||||||
|
<template #button>
|
||||||
|
<van-button plain round type="primary" size="mini" @click="getCurrentTime">校准时间</van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field v-model="form.event.occurLocation" label="发生地点" center placeholder="请填写" />
|
||||||
|
<van-field v-model="form.event.routeNo" label="线路编号" center placeholder="请填写" />
|
||||||
|
<van-field v-model="form.event.startStakeNo" label="起点桩号" center placeholder="请填写" />
|
||||||
|
<van-field v-model="form.event.endStakeNo" label="止点桩号" center placeholder="请填写" />
|
||||||
|
<van-field v-model="form.event.disasterMileage" label="受灾里程" center type="number" placeholder="请填写" />
|
||||||
|
</van-form>
|
||||||
|
</PanelItem>
|
||||||
|
|
||||||
|
<PanelItem title="处置情况">
|
||||||
|
<van-form class="IceEventAddForm" label-align="left" colon>
|
||||||
|
<van-field label="处置措施" center>
|
||||||
|
<template #input>
|
||||||
|
<div class="disposal-buttons">
|
||||||
|
<van-button plain :type="form.event.disposalMeasures === '限速通行' ? 'primary' : 'default'" size="small" @click="toggleDisposal('限速通行')">
|
||||||
|
限速通行
|
||||||
|
</van-button>
|
||||||
|
<van-button plain :type="form.event.disposalMeasures === '封闭交通' ? 'primary' : 'default'" size="small" @click="toggleDisposal('封闭交通')" class="last-button">
|
||||||
|
封闭交通
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field v-model="form.event.expectRecoverTime" label="预计恢复时间" center placeholder="请选择" readonly clickable @click="showExpectPicker = true" />
|
||||||
|
<van-popup :show="showExpectPicker" round position="bottom" close-on-click-overlay @close="showExpectPicker = false">
|
||||||
|
<van-picker-group title="选择日期时间" :tabs="['选择日期', '选择时间']" @confirm="handleConfirmExpectTime" @cancel="showExpectPicker = false">
|
||||||
|
<van-date-picker v-model="expectDate" :min-date="minDate" :max-date="maxDate" />
|
||||||
|
<van-time-picker v-model="expectTime" />
|
||||||
|
</van-picker-group>
|
||||||
|
</van-popup>
|
||||||
|
</van-form>
|
||||||
|
</PanelItem>
|
||||||
|
|
||||||
|
<PanelItem title="实施情况">
|
||||||
|
<van-form class="IceEventAddForm" label-align="left" colon>
|
||||||
|
<van-field v-model="form.material.inputManpower" type="number" label="投入人力" center placeholder="请填写">
|
||||||
|
<template #extra> 人次 </template>
|
||||||
|
</van-field>
|
||||||
|
<van-field v-model="form.material.inputFunds" type="number" label="投入资金" center placeholder="请填写">
|
||||||
|
<template #extra> 万元 </template>
|
||||||
|
</van-field>
|
||||||
|
<van-field v-model="form.material.inputEquipment" type="number" label="投入设备" center placeholder="请填写">
|
||||||
|
<template #extra> 台班 </template>
|
||||||
|
</van-field>
|
||||||
|
|
||||||
|
<!-- 选择物资列表 -->
|
||||||
|
<van-field
|
||||||
|
v-for="(material, index) in form.yhzMaterialList"
|
||||||
|
:key="material.rid"
|
||||||
|
v-model="material.usageAmount"
|
||||||
|
type="number"
|
||||||
|
@input="checkMaterialAmount(material, index)"
|
||||||
|
:label="material.wzmc"
|
||||||
|
center
|
||||||
|
:placeholder="`余额: ${material.ye} `"
|
||||||
|
>
|
||||||
|
<template #extra>
|
||||||
|
<span style="margin-right: 10px">{{ material.dw }}</span>
|
||||||
|
<van-button size="small" type="danger" @click.stop="form.yhzMaterialList.splice(index, 1)"> 删除 </van-button>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
|
||||||
|
<van-button class="add-wzbtn" type="primary" icon="plus" plain @click="handleOpenAddMaterial">添加物资 </van-button>
|
||||||
|
<van-popup :show="showAddMaterialPopup" position="bottom" close-on-click-overlay @close="showAddMaterialPopup = false">
|
||||||
|
<div style="padding: 16px">
|
||||||
|
<h3 style="text-align: center; margin-bottom: 16px">添加物资</h3>
|
||||||
|
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<van-field v-model="searchText" placeholder="输入物资名称搜索" clearable @update:model-value="handleSearch"> </van-field>
|
||||||
|
|
||||||
|
<van-checkbox-group v-model="checked">
|
||||||
|
<van-cell-group inset style="margin: 16px 0">
|
||||||
|
<div style="display: flex; justify-content: space-between; padding: 8px 16px">
|
||||||
|
<span>共 {{ materialList.length }} 项</span>
|
||||||
|
<van-button size="mini" @click="toggleSelectAll" :type="isAllSelected ? 'primary' : 'default'">
|
||||||
|
{{ isAllSelected ? '取消全选' : '全选' }}
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
<van-cell v-for="(item, index) in materialList" clickable :key="item.rid" :title="item.wzmc" @click="toggle(index)">
|
||||||
|
<template #right-icon>
|
||||||
|
<van-checkbox :name="item.rid" :ref="(el) => (checkboxRefs[index] = el)" @click.stop />
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
</van-checkbox-group>
|
||||||
|
|
||||||
|
<van-button type="primary" block @click="addSelectedMaterials" style="margin-top: 10px"> 确认添加 </van-button>
|
||||||
|
</div>
|
||||||
|
</van-popup>
|
||||||
|
|
||||||
|
<van-field label="当前通行情况" center>
|
||||||
|
<template #input>
|
||||||
|
<div class="disposal-buttons">
|
||||||
|
<van-button plain :type="form.traffic.currentStatus === 1 ? 'primary' : 'default'" size="small" @click="form.traffic.currentStatus = 1"> 正常通行 </van-button>
|
||||||
|
<van-button plain :type="form.traffic.currentStatus === 2 ? 'primary' : 'default'" size="small" @click="form.traffic.currentStatus = 2"> 限速通行 </van-button>
|
||||||
|
<van-button plain :type="form.traffic.currentStatus === 3 ? 'primary' : 'default'" size="small" @click="form.traffic.currentStatus = 3" class="last-button">
|
||||||
|
封闭交通
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field label="有无车辆滞留" center>
|
||||||
|
<template #input>
|
||||||
|
<div class="disposal-buttons">
|
||||||
|
<van-button plain :type="form.traffic.hasStrandedVehicles === 1 ? 'primary' : 'default'" size="small" @click="form.traffic.hasStrandedVehicles = 1">
|
||||||
|
有滞留
|
||||||
|
</van-button>
|
||||||
|
<van-button
|
||||||
|
plain
|
||||||
|
:type="form.traffic.hasStrandedVehicles === 0 ? 'primary' : 'default'"
|
||||||
|
size="small"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
form.traffic.hasStrandedVehicles = 0
|
||||||
|
form.traffic.strandedVehicleCount = null
|
||||||
|
}
|
||||||
|
"
|
||||||
|
class="last-button"
|
||||||
|
>
|
||||||
|
无滞留
|
||||||
|
</van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
<van-field v-if="form.traffic.hasStrandedVehicles === 1" v-model="form.traffic.strandedVehicleCount" type="number" label="滞留车辆数" center placeholder="请填写" />
|
||||||
|
|
||||||
|
<van-field v-model="form.traffic.actualRecoverTime" label="实际恢复时间" center placeholder="请选择" readonly clickable @click="showActualPicker = true" />
|
||||||
|
<van-popup :show="showActualPicker" round position="bottom" close-on-click-overlay @close="showActualPicker = false">
|
||||||
|
<van-picker-group title="选择日期时间" :tabs="['选择日期', '选择时间']" @confirm="handleConfirmActualTime" @cancel="showActualPicker = false">
|
||||||
|
<van-date-picker v-model="actualDate" :min-date="minDate" :max-date="maxDate" />
|
||||||
|
<van-time-picker v-model="actualTime" />
|
||||||
|
</van-picker-group>
|
||||||
|
</van-popup>
|
||||||
|
|
||||||
|
<van-field label="附件" center>
|
||||||
|
<template #input>
|
||||||
|
<van-uploader
|
||||||
|
v-model="fileList"
|
||||||
|
@delete="handleDelete"
|
||||||
|
name="photos"
|
||||||
|
:file-list="fileList"
|
||||||
|
:file-type="['image/jpeg', 'image/png']"
|
||||||
|
:after-read="afterRead"
|
||||||
|
multiple
|
||||||
|
:max-count="6"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</van-field>
|
||||||
|
</van-form>
|
||||||
|
</PanelItem>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<van-button type="primary" class="add-btn" @click="handleAdd"> 提交 </van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, reactive, toRaw, watch, computed } from 'vue'
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
import { showToast, showLoadingToast } from 'vant'
|
||||||
|
import PanelItem from '@/components/PanelItem.vue'
|
||||||
|
import { request } from '../../../../shared/utils/request'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
const yhzDetail = ref({}) // 养护站详情数据
|
||||||
|
const INIT_FORM = reactive({
|
||||||
|
event: {
|
||||||
|
occurLocation: '', // 发生地点
|
||||||
|
routeNo: '', // 线路编号
|
||||||
|
occurTime: '', // 发生时间
|
||||||
|
startStakeNo: '', // 起点桩号
|
||||||
|
endStakeNo: '', // 止点桩号
|
||||||
|
disasterMileage: '', // 受灾里程
|
||||||
|
expectRecoverTime: '', // 预计恢复时间
|
||||||
|
actualRecoverTime: '', // 实际恢复时间
|
||||||
|
serviceStationId: '', // 养护站ID
|
||||||
|
district: '', // 所属区县
|
||||||
|
reportTime: '', // 填报时间
|
||||||
|
reporterPhone: '', // 填报人手机号
|
||||||
|
disposalMeasures: '', // 处置措施
|
||||||
|
createTime: '', // 创建时间
|
||||||
|
updateTime: '', // 更新时间
|
||||||
|
isDeleted: '' // 是否删除 0-未删除 1-已删除
|
||||||
|
},
|
||||||
|
material: {
|
||||||
|
inputManpower: null, // 投入人力
|
||||||
|
inputFunds: null, // 投入资金
|
||||||
|
inputEquipment: null, // 投入设备
|
||||||
|
createTime: '', // 创建时间
|
||||||
|
updateTime: '' // 更新时间
|
||||||
|
},
|
||||||
|
traffic: {
|
||||||
|
currentStatus: 0, // 当前通行情况 1-正常通行 2-限速通行 3-封闭交通
|
||||||
|
hasStrandedVehicles: 0, // 是否有车辆滞留 0-无 1-有
|
||||||
|
strandedVehicleCount: null, // 车辆滞留数量
|
||||||
|
actualRecoverTime: '', // 实际恢复时间
|
||||||
|
createTime: '', // 创建时间
|
||||||
|
updateTime: '' // 更新时间
|
||||||
|
},
|
||||||
|
yhzMaterialList: [], // 养护站物资列表
|
||||||
|
photos: []
|
||||||
|
})
|
||||||
|
const form = reactive({ ...INIT_FORM })
|
||||||
|
const fileList = ref([])
|
||||||
|
|
||||||
|
// 日期格式化
|
||||||
|
const formatTime = (date = new Date()) => {
|
||||||
|
const pad = (n) => n.toString().padStart(2, '0')
|
||||||
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` + `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCurrentTime = () => {
|
||||||
|
form.event.occurTime = formatTime()
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleDisposal = (type) => {
|
||||||
|
form.event.disposalMeasures = form.event.disposalMeasures === type ? '' : type
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
onMounted(() => {
|
||||||
|
form.event.occurTime = formatTime() // 初始化为当前时间
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加物资相关
|
||||||
|
const showAddMaterialPopup = ref(false)
|
||||||
|
const materialList = ref([])
|
||||||
|
const checkboxRefs = ref([])
|
||||||
|
const checked = ref([])
|
||||||
|
const toggle = (index) => {
|
||||||
|
checkboxRefs.value[index].toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchText = ref('')
|
||||||
|
const handleSearch = () => {
|
||||||
|
getMaterialList(searchText.value)
|
||||||
|
}
|
||||||
|
// 全选功能
|
||||||
|
const toggleSelectAll = () => {
|
||||||
|
if (isAllSelected.value) {
|
||||||
|
checked.value = []
|
||||||
|
} else {
|
||||||
|
checked.value = materialList.value.map((item) => item.rid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 计算是否全选
|
||||||
|
const isAllSelected = computed(() => {
|
||||||
|
return materialList.value.length > 0 && materialList.value.every((item) => checked.value.includes(item.rid))
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加物资到表单
|
||||||
|
const addSelectedMaterials = () => {
|
||||||
|
checked.value.forEach((rid) => {
|
||||||
|
const material = materialList.value.find((m) => m.rid === rid)
|
||||||
|
if (material && !form.yhzMaterialList.some((m) => m.rid === rid)) {
|
||||||
|
form.yhzMaterialList.push({
|
||||||
|
rid: rid,
|
||||||
|
wzmc: material.wzmc,
|
||||||
|
usageAmount: null,
|
||||||
|
dw: material.dw,
|
||||||
|
ye: material.ye
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
showAddMaterialPopup.value = false
|
||||||
|
checked.value = []
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查余额
|
||||||
|
const checkMaterialAmount = (material, index) => {
|
||||||
|
if (material.usageAmount > material.ye) {
|
||||||
|
showToast({
|
||||||
|
type: 'fail',
|
||||||
|
message: '输入数量不能超过物资余额'
|
||||||
|
})
|
||||||
|
// 设置为最大值
|
||||||
|
form.yhzMaterialList[index].usageAmount = material.ye
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询物资列表
|
||||||
|
const getMaterialList = async (wzmc) => {
|
||||||
|
try {
|
||||||
|
const data = {
|
||||||
|
yhzid: yhzDetail.value.id,
|
||||||
|
wzmc,
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 9999
|
||||||
|
}
|
||||||
|
const res = await request({
|
||||||
|
url: '/snow-ops-platform/yjwz/list',
|
||||||
|
method: 'GET',
|
||||||
|
params: data
|
||||||
|
})
|
||||||
|
if (res.code === '00000') {
|
||||||
|
materialList.value = res.data.records
|
||||||
|
} else {
|
||||||
|
throw new Error(res.message)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showToast({
|
||||||
|
type: 'fail',
|
||||||
|
message: error.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开添加物资弹窗
|
||||||
|
const handleOpenAddMaterial = async () => {
|
||||||
|
await getMaterialList()
|
||||||
|
showAddMaterialPopup.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = async () => {
|
||||||
|
try {
|
||||||
|
const toast = showLoadingToast({
|
||||||
|
message: '上报中...',
|
||||||
|
forbidClick: true,
|
||||||
|
duration: 0 // 设置为0表示不会自动关闭
|
||||||
|
})
|
||||||
|
form.event.serviceStationId = yhzDetail.value.id
|
||||||
|
form.event.district = yhzDetail.value.qxmc
|
||||||
|
console.log('yhzDetail', toRaw(yhzDetail.value))
|
||||||
|
console.log('form', toRaw(form))
|
||||||
|
const res = await request({
|
||||||
|
url: '/snow-ops-platform/event/add',
|
||||||
|
method: 'POST',
|
||||||
|
data: form
|
||||||
|
})
|
||||||
|
if (res.code === '00000') {
|
||||||
|
toast.close()
|
||||||
|
showToast({
|
||||||
|
type: 'success',
|
||||||
|
message: '上报成功'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
router.replace('/disasterManagement')
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
toast.close()
|
||||||
|
throw new Error(res.message)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showToast({
|
||||||
|
type: 'fail',
|
||||||
|
message: error.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const expectDate = ref([])
|
||||||
|
const expectTime = ref([])
|
||||||
|
const actualDate = ref([])
|
||||||
|
const actualTime = ref([])
|
||||||
|
|
||||||
|
// 预计恢复时间相关
|
||||||
|
const showExpectPicker = ref(false)
|
||||||
|
const minDate = new Date()
|
||||||
|
const maxDate = new Date(2050, 11, 31)
|
||||||
|
const handleConfirmExpectTime = () => {
|
||||||
|
const [year, month, day] = expectDate.value
|
||||||
|
const [hour, minute] = expectTime.value
|
||||||
|
form.event.expectRecoverTime =
|
||||||
|
`${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')} ` + `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`
|
||||||
|
showExpectPicker.value = false
|
||||||
|
}
|
||||||
|
// 实际恢复时间相关
|
||||||
|
const showActualPicker = ref(false)
|
||||||
|
const handleConfirmActualTime = () => {
|
||||||
|
const [year, month, day] = actualDate.value
|
||||||
|
const [hour, minute] = actualTime.value
|
||||||
|
form.traffic.actualRecoverTime =
|
||||||
|
`${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')} ` + `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:00`
|
||||||
|
showActualPicker.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在打开选择器时设置初始值
|
||||||
|
watch(showExpectPicker, (val) => {
|
||||||
|
if (val) {
|
||||||
|
const current = form.event.expectRecoverTime ? new Date(form.event.expectRecoverTime) : new Date()
|
||||||
|
expectDate.value = [current.getFullYear(), current.getMonth() + 1, current.getDate()]
|
||||||
|
expectTime.value = [current.getHours(), current.getMinutes()]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
watch(showActualPicker, (val) => {
|
||||||
|
if (val) {
|
||||||
|
const current = form.traffic.actualRecoverTime ? new Date(form.traffic.actualRecoverTime) : new Date()
|
||||||
|
actualDate.value = [current.getFullYear(), current.getMonth() + 1, current.getDate()]
|
||||||
|
actualTime.value = [current.getHours(), current.getMinutes()]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 文件上传
|
||||||
|
const afterRead = async (file) => {
|
||||||
|
try {
|
||||||
|
const toast = showLoadingToast({
|
||||||
|
message: '上传中...',
|
||||||
|
forbidClick: true,
|
||||||
|
duration: 0 // 设置为0表示不会自动关闭
|
||||||
|
})
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file.file)
|
||||||
|
const res = await request({
|
||||||
|
url: '/snow-ops-platform/file/upload',
|
||||||
|
method: 'post',
|
||||||
|
data: formData
|
||||||
|
})
|
||||||
|
toast.close()
|
||||||
|
if (res.code === '00000') {
|
||||||
|
form.photos.push({ photoUrl: res.data })
|
||||||
|
const index = fileList.value.findIndex((f) => f.file === file.file)
|
||||||
|
if (index !== -1) {
|
||||||
|
fileList.value[index].serverUrl = res.data
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('form.photos', toRaw(form.photos))
|
||||||
|
console.log('fileList.value', fileList.value)
|
||||||
|
} else {
|
||||||
|
throw new Error(res.message)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.close()
|
||||||
|
showToast({
|
||||||
|
type: 'fail',
|
||||||
|
message: error.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文件删除
|
||||||
|
const handleDelete = (file) => {
|
||||||
|
if (file.serverUrl) {
|
||||||
|
const index = form.photos.findIndex((p) => p.photoUrl === file.serverUrl)
|
||||||
|
if (index !== -1) {
|
||||||
|
form.photos.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.home {
|
||||||
|
/* 自动匹配导航栏高度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
}
|
||||||
|
|
||||||
|
.content .van-cell-group .van-cell {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-wzbtn {
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
margin: 10px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 16px;
|
||||||
|
right: 16px;
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
margin: 0 auto;
|
||||||
|
border-radius: 24px;
|
||||||
|
font-size: 16px;
|
||||||
|
height: 44px;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-good {
|
||||||
|
background-color: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-warning {
|
||||||
|
background-color: #ff976a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-danger {
|
||||||
|
background-color: #ee0a24;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disposal-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disposal-buttons .van-button {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.last-button {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,313 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mobile-selector">
|
||||||
|
<!-- 只读输入框,点击打开选择器 -->
|
||||||
|
<!-- <div class="selector-input" @click="openPicker">
|
||||||
|
<span class="selector-value" :class="{ 'placeholder': !displayValue }">
|
||||||
|
{{ displayValue || placeholder }}
|
||||||
|
</span>
|
||||||
|
<van-icon name="arrow-down" class="selector-icon" />
|
||||||
|
</div> -->
|
||||||
|
<van-field :modelValue="modelValue" is-link readonly :label="label" :placeholder="placeholder" @click="showPicker = true" />
|
||||||
|
|
||||||
|
<!-- 移动端弹出层(使用 van-action-sheet + 内部列表) -->
|
||||||
|
<van-action-sheet v-model:show="showPicker" :title="dialogTitle" :close-on-click-action="false" round :style="{ maxHeight: '80vh' }" @close="handlePickerClose">
|
||||||
|
<div class="picker-content">
|
||||||
|
<!-- 已选择提示 -->
|
||||||
|
<div class="selected-tip" v-if="tempSelectedItem">已选择路线:{{ tempSelectedItem.routeCode }}</div>
|
||||||
|
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<van-search v-model="searchKeyword" :placeholder="searchPlaceholder" clearable @input="handleSearchInput" @clear="handleSearchClear" />
|
||||||
|
|
||||||
|
<!-- 列表区域 -->
|
||||||
|
<van-list v-model:loading="listLoading" :finished="finished" finished-text="没有更多了" @load="onLoadMore" :immediate-check="false">
|
||||||
|
<van-cell
|
||||||
|
v-for="item in dataList"
|
||||||
|
:key="item.routeCode"
|
||||||
|
:title="item.routeCode"
|
||||||
|
:class="{ 'is-selected': tempSelectedItem?.routeCode === item.routeCode }"
|
||||||
|
@click="handleItemClick(item)"
|
||||||
|
/>
|
||||||
|
<van-empty v-if="!listLoading && dataList.length === 0" description="暂无数据" />
|
||||||
|
</van-list>
|
||||||
|
</div>
|
||||||
|
</van-action-sheet>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, watch, onUnmounted } from 'vue'
|
||||||
|
import { showToast } from 'vant'
|
||||||
|
import { request } from '@shared/utils/request'
|
||||||
|
|
||||||
|
// ==================== Props ====================
|
||||||
|
const props = defineProps({
|
||||||
|
// v-model 绑定的值(路线编号)
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 占位符文本
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请选择路线'
|
||||||
|
},
|
||||||
|
// 弹窗标题
|
||||||
|
dialogTitle: {
|
||||||
|
type: String,
|
||||||
|
default: '选择地点路线'
|
||||||
|
},
|
||||||
|
// 搜索框占位符
|
||||||
|
searchPlaceholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请输入路线编号'
|
||||||
|
},
|
||||||
|
// 请求接口地址
|
||||||
|
apiUrl: {
|
||||||
|
type: String,
|
||||||
|
default: '/snow-ops-platform/infrastructure-asset/routes'
|
||||||
|
},
|
||||||
|
// 每页大小(移动端常用固定分页,也可配置)
|
||||||
|
pageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 20
|
||||||
|
},
|
||||||
|
// 额外请求参数
|
||||||
|
extraParams: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
// 搜索防抖延迟时间(ms)
|
||||||
|
searchDelay: {
|
||||||
|
type: Number,
|
||||||
|
default: 500
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
|
|
||||||
|
// ==================== 状态 ====================
|
||||||
|
const showPicker = ref(false) // 控制弹出层显示
|
||||||
|
const searchKeyword = ref('') // 搜索关键词
|
||||||
|
const dataList = ref([]) // 当前已加载的数据列表
|
||||||
|
const listLoading = ref(false) // 是否正在加载更多
|
||||||
|
const finished = ref(false) // 是否已加载全部
|
||||||
|
const currentPage = ref(1) // 当前页码
|
||||||
|
const total = ref(0) // 总记录数
|
||||||
|
|
||||||
|
// 临时选中的数据(确认前暂存,移动端点击即选中并关闭)
|
||||||
|
const tempSelectedItem = ref(null)
|
||||||
|
|
||||||
|
// 防抖定时器
|
||||||
|
let searchTimer = null
|
||||||
|
|
||||||
|
// 显示值:优先显示已确认选中的 routeCode
|
||||||
|
const displayValue = computed(() => {
|
||||||
|
return props.modelValue || ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听外部 modelValue 变化,清空临时选中标记(当外部值改变时)
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(newVal) => {
|
||||||
|
if (tempSelectedItem.value && tempSelectedItem.value.routeCode !== newVal) {
|
||||||
|
tempSelectedItem.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// ==================== API 请求 ====================
|
||||||
|
// 加载数据(支持分页追加或重置)
|
||||||
|
const fetchData = async (isReset = true) => {
|
||||||
|
if (isReset) {
|
||||||
|
// 重置时清空列表,重置页码
|
||||||
|
currentPage.value = 1
|
||||||
|
dataList.value = []
|
||||||
|
finished.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finished.value && !isReset) return
|
||||||
|
|
||||||
|
listLoading.value = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
pageNum: currentPage.value,
|
||||||
|
pageSize: props.pageSize,
|
||||||
|
lxbh: searchKeyword.value || props.modelValue || undefined,
|
||||||
|
xzdj: props.extraParams?.xzdj,
|
||||||
|
qxid: props.extraParams?.qxid
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await request({
|
||||||
|
url: props.apiUrl,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response?.code === '00000') {
|
||||||
|
const records = response.data.records || []
|
||||||
|
total.value = response.data.total || 0
|
||||||
|
|
||||||
|
if (isReset) {
|
||||||
|
dataList.value = records
|
||||||
|
} else {
|
||||||
|
dataList.value = [...dataList.value, ...records]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否已加载全部
|
||||||
|
finished.value = dataList.value.length >= total.value
|
||||||
|
} else {
|
||||||
|
showToast(response.message || '加载失败')
|
||||||
|
if (isReset) dataList.value = []
|
||||||
|
finished.value = true
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('请求失败:', error)
|
||||||
|
showToast('加载失败,请重试')
|
||||||
|
if (isReset) dataList.value = []
|
||||||
|
finished.value = true
|
||||||
|
} finally {
|
||||||
|
listLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多(van-list 的 load 事件)
|
||||||
|
const onLoadMore = () => {
|
||||||
|
if (finished.value) return
|
||||||
|
currentPage.value++
|
||||||
|
fetchData(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 防抖搜索函数
|
||||||
|
const debouncedSearch = () => {
|
||||||
|
if (searchTimer) clearTimeout(searchTimer)
|
||||||
|
searchTimer = setTimeout(() => {
|
||||||
|
// 重置列表并重新加载第一页
|
||||||
|
currentPage.value = 1
|
||||||
|
fetchData(true)
|
||||||
|
}, props.searchDelay)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 事件处理 ====================
|
||||||
|
const openPicker = () => {
|
||||||
|
showPicker.value = true
|
||||||
|
// 打开时重置临时选中状态(基于当前已选中的值)
|
||||||
|
if (props.modelValue) {
|
||||||
|
tempSelectedItem.value = { routeCode: props.modelValue }
|
||||||
|
} else {
|
||||||
|
tempSelectedItem.value = null
|
||||||
|
}
|
||||||
|
// 清空搜索关键词(可选,视需求决定是否保留)
|
||||||
|
searchKeyword.value = ''
|
||||||
|
// 重置分页并加载数据
|
||||||
|
currentPage.value = 1
|
||||||
|
fetchData(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePickerClose = () => {
|
||||||
|
showPicker.value = false
|
||||||
|
// 清除防抖定时器
|
||||||
|
if (searchTimer) clearTimeout(searchTimer)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearchInput = () => {
|
||||||
|
debouncedSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearchClear = () => {
|
||||||
|
searchKeyword.value = ''
|
||||||
|
debouncedSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击某一项:立即选中并关闭弹窗
|
||||||
|
const handleItemClick = (item) => {
|
||||||
|
tempSelectedItem.value = item
|
||||||
|
// 更新 v-model 值
|
||||||
|
emit('update:modelValue', item.routeCode)
|
||||||
|
emit('change', item)
|
||||||
|
// 关闭选择器
|
||||||
|
showPicker.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==================== 清理定时器 ====================
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (searchTimer) clearTimeout(searchTimer)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.mobile-selector {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.selector-input {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 12px;
|
||||||
|
background-color: #f7f8fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.4;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
min-height: 44px; // 移动端触摸区域
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #ebedf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-value {
|
||||||
|
flex: 1;
|
||||||
|
color: #323233;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.placeholder {
|
||||||
|
color: #c8c9cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector-icon {
|
||||||
|
color: #969799;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 80vh;
|
||||||
|
|
||||||
|
.selected-tip {
|
||||||
|
padding: 12px 16px;
|
||||||
|
background-color: #f0f9eb;
|
||||||
|
color: #67c23a;
|
||||||
|
font-size: 13px;
|
||||||
|
border-bottom: 1px solid #e9e9e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 覆盖 van-list 内部样式,让滚动更自然
|
||||||
|
:deep(.van-list) {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.van-cell {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
|
||||||
|
&.is-selected {
|
||||||
|
color: #1989fa;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -4,13 +4,13 @@
|
|||||||
<PanelItem title="基本信息" v-if="!isContinue">
|
<PanelItem title="基本信息" v-if="!isContinue">
|
||||||
<van-form>
|
<van-form>
|
||||||
<!-- 路况类别 -->
|
<!-- 路况类别 -->
|
||||||
<BasePicker v-model="formData.roadConditionType" :options="roadConditionOptions" label="路况类别" placeholder="请选择" />
|
<BasePicker v-model="formData.roadConditionType" :options="options['roadConditionType']" label="路况类别" placeholder="请选择" />
|
||||||
|
|
||||||
<!-- 是否阻断 (event.isBlocked) -->
|
<!-- 是否阻断 (event.isBlocked) -->
|
||||||
<BasePicker v-model="formData.event.isBlocked" :options="blockedOptions" label="是否阻断" placeholder="请选择" />
|
<BasePicker v-model="formData.event.isBlocked" :options="options['yesNoBool']" label="是否阻断" placeholder="请选择" />
|
||||||
|
|
||||||
<!-- 抢险进度 (event.repairProgress) -->
|
<!-- 抢险进度 (event.repairProgress) -->
|
||||||
<BasePicker v-model="formData.event.repairProgress" :options="repairProgressOptions" label="抢险进度" placeholder="请选择" />
|
<BasePicker v-model="formData.event.repairProgress" :options="options['repairProgress']" label="抢险进度" placeholder="请选择" />
|
||||||
|
|
||||||
<!-- 水毁处数 (event.damageCount) -->
|
<!-- 水毁处数 (event.damageCount) -->
|
||||||
<van-field v-model="formData.event.damageCount" label="水毁处数" placeholder="请填写" type="number" />
|
<van-field v-model="formData.event.damageCount" label="水毁处数" placeholder="请填写" type="number" />
|
||||||
@ -30,7 +30,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 线路编号 (顶层 routeNo) -->
|
<!-- 线路编号 (顶层 routeNo) -->
|
||||||
<van-field v-model="formData.routeNo" label="线路编号" placeholder="请填写" />
|
<RoadRoutesPicker v-model="formData.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="请填写" />
|
||||||
@ -38,6 +38,10 @@
|
|||||||
<!-- 止点桩号 (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.longitude" label="经度" placeholder="请填写" />
|
||||||
|
|
||||||
|
<van-field v-model="formData.event.latitude" label="纬度" placeholder="请填写" />
|
||||||
|
|
||||||
<!-- 路况位置 (occurLocation) -->
|
<!-- 路况位置 (occurLocation) -->
|
||||||
<van-field v-model="formData.occurLocation" label="路况位置" placeholder="请填写" />
|
<van-field v-model="formData.occurLocation" label="路况位置" placeholder="请填写" />
|
||||||
|
|
||||||
@ -51,13 +55,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-radio-group -->
|
<van-row gutter="10">
|
||||||
<van-radio-group v-model="formData.report.disposalMeasures" direction="horizontal">
|
<van-col v-for="(item, index) in options['disposalMeasures']" :span="24 / options['disposalMeasures'].length" :key="index">
|
||||||
<van-radio name="半幅封闭">半幅封闭</van-radio>
|
<van-button block plain :type="item.value === formData.report.disposalMeasures ? 'primary' : 'default'" @click="formData.report.disposalMeasures = item.value">
|
||||||
<van-radio name="全副封闭">全副封闭</van-radio>
|
{{ item.label }}
|
||||||
<van-radio name="便道通行">便道通行</van-radio>
|
</van-button>
|
||||||
<van-radio name="正常通行">正常通行</van-radio>
|
</van-col>
|
||||||
</van-radio-group>
|
</van-row>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -130,44 +134,49 @@
|
|||||||
<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 />
|
||||||
<van-field label="附件" center>
|
<van-field label="附件" center>
|
||||||
<template #input>
|
<template #input>
|
||||||
<van-uploader accept="video/*,image/*" :modelValue="getFileList()" :after-read="afterRead" multiple :max-count="6" @delete="removeFile" />
|
<van-uploader accept="video/*,image/*" :modelValue="getFileList()" :after-read="afterRead" multiple :max-count="7" @delete="removeFile" />
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
</PanelItem>
|
</PanelItem>
|
||||||
<PanelItem>
|
<PanelItem v-if="!isContinue || (isContinue && !detail?.event.needsRecovery)">
|
||||||
<!-- 是否需要恢复重建 (event.needsRecovery) -->
|
<!-- 是否需要恢复重建 (event.needsRecovery) -->
|
||||||
<BasePicker v-model="formData.event.needsRecovery" :options="needsRecoveryOptions" label="是否需要恢复重建" placeholder="请选择" />
|
<BasePicker v-model="formData.event.needsRecovery" :options="options['yesNoBool']" label="是否需要恢复重建" placeholder="请选择" />
|
||||||
<!-- 恢复重建预估费用 (event.estimatedRecoveryCost) -->
|
<!-- 恢复重建预估费用 (event.estimatedRecoveryCost) -->
|
||||||
<van-field v-model="formData.event.estimatedRecoveryCost" v-if="!isContinue" label="恢复重建预估费用" placeholder="请填写" type="digit">
|
<van-field v-model="formData.event.estimatedRecoveryCost" v-if="formData?.event.needsRecovery" label="恢复重建预估费用" placeholder="请填写" type="digit">
|
||||||
<template #button>
|
<template #button>
|
||||||
<span class="field-unit">万元</span>
|
<span class="field-unit">万元</span>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
|
<!-- 提交按钮 -->
|
||||||
|
<van-button type="primary" class="footer-btn" @click="handleSubmit" :loading="submitting"> 提交 </van-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, watch } from 'vue'
|
import { ref, computed, watch, onMounted } from 'vue'
|
||||||
import { showToast, showFailToast, showLoadingToast } from 'vant'
|
import { showToast, showFailToast, showLoadingToast } from 'vant'
|
||||||
import PanelItem from '@/components/PanelItem.vue'
|
import PanelItem from '@/components/PanelItem.vue'
|
||||||
import BasePicker from '@/components/BasePicker.vue'
|
import BasePicker from '@/components/BasePicker.vue'
|
||||||
import BaseDatePicker from '@/components/BaseDatePicker.vue'
|
import BaseDatePicker from '@/components/BaseDatePicker.vue'
|
||||||
|
import RoadRoutesPicker from '../RoadRoutesPicker.vue'
|
||||||
import LossList from './LossList.vue'
|
import LossList from './LossList.vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { request } from '@shared/utils/request'
|
import { request } from '@shared/utils/request'
|
||||||
|
import { useOptions } from '@shared/composables/useOptions'
|
||||||
|
import mockFormData from '../waterDisasterFormData.json'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const { options } = useOptions()
|
||||||
// 是否为续报
|
// 是否为续报
|
||||||
const isContinue = computed(() => route.query.isContinue)
|
const isContinue = computed(() => route.query.isContinue)
|
||||||
|
|
||||||
|
|
||||||
// 表单数据 - 按 Request 接口结构定义,使用 ref 包装
|
// 表单数据 - 按 Request 接口结构定义,使用 ref 包装
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
// 顶层字段
|
// 顶层字段
|
||||||
occurLocation: '', // 发生地点
|
occurLocation: '', // 发生地点
|
||||||
occurTime: '', // 发生时间
|
occurTime: null, // 发生时间
|
||||||
roadConditionType: '', // 路况类别
|
roadConditionType: '', // 路况类别
|
||||||
routeNo: '', // 线路编号
|
routeNo: '', // 线路编号
|
||||||
|
|
||||||
@ -225,31 +234,7 @@ const getFileList = () => {
|
|||||||
return fileList
|
return fileList
|
||||||
}
|
}
|
||||||
|
|
||||||
// BasePicker 选项数据
|
const submitting = ref(false)
|
||||||
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 needsRecoveryOptions = [
|
|
||||||
{ label: '是', value: true },
|
|
||||||
{ label: '否', value: false }
|
|
||||||
]
|
|
||||||
|
|
||||||
// 时间选择器范围
|
// 时间选择器范围
|
||||||
const minDate = new Date(2020, 0, 1)
|
const minDate = new Date(2020, 0, 1)
|
||||||
@ -260,7 +245,7 @@ const initFormData = (newVal) => {
|
|||||||
// 深度合并数据 - 直接替换整个对象
|
// 深度合并数据 - 直接替换整个对象
|
||||||
formData.value = {
|
formData.value = {
|
||||||
occurLocation: newVal.occurLocation || '',
|
occurLocation: newVal.occurLocation || '',
|
||||||
occurTime: newVal.occurTime || '',
|
occurTime: newVal.occurTime || formatTime(),
|
||||||
roadConditionType: newVal.roadConditionType || '',
|
roadConditionType: newVal.roadConditionType || '',
|
||||||
routeNo: newVal.routeNo || '',
|
routeNo: newVal.routeNo || '',
|
||||||
event: { ...formData.value.event, ...(newVal.event || {}) },
|
event: { ...formData.value.event, ...(newVal.event || {}) },
|
||||||
@ -311,6 +296,11 @@ const isVideoFile = (file) => {
|
|||||||
if (file.fileUrl && videoExtensions.test(file.fileUrl)) return true
|
if (file.fileUrl && videoExtensions.test(file.fileUrl)) return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleRouteNoChange = (item) => {
|
||||||
|
formData.value.event.startStakeNo = item.startStakeNo
|
||||||
|
formData.value.event.endStakeNo = item.endStakeNo
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断图片是否可以上传
|
* 判断图片是否可以上传
|
||||||
* @param {File} file - 图片文件
|
* @param {File} file - 图片文件
|
||||||
@ -371,11 +361,23 @@ const isValidVideo = (file) => {
|
|||||||
const checkFile = (file) => {
|
const checkFile = (file) => {
|
||||||
// 判断是否为图片
|
// 判断是否为图片
|
||||||
if (file.type.startsWith('image/')) {
|
if (file.type.startsWith('image/')) {
|
||||||
|
const imageCount = formData.value.fileList?.filter((item) => item.fileType === 1).length
|
||||||
|
if (imageCount == 6) {
|
||||||
|
showFailToast('只能上传六张图片!')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return isValidImage(file)
|
return isValidImage(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否为视频
|
// 判断是否为视频
|
||||||
if (file.type.startsWith('video/')) {
|
if (file.type.startsWith('video/')) {
|
||||||
|
const videoCount = formData.value.fileList?.filter((item) => item.fileType === 2).length
|
||||||
|
if (videoCount == 1) {
|
||||||
|
showFailToast('只能上传一个视频文件!')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return isValidVideo(file)
|
return isValidVideo(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,9 +404,8 @@ const afterRead = async (options) => {
|
|||||||
toast.close()
|
toast.close()
|
||||||
if (res.code === '00000') {
|
if (res.code === '00000') {
|
||||||
const name = file.name
|
const name = file.name
|
||||||
let type = isImageFile(file) ? 1 : isVideoFile(file) ? 2 : 3
|
|
||||||
|
|
||||||
const url = res.data
|
const url = res.data
|
||||||
|
const type = isImageFile({ fileUrl: url}) ? 1 : isVideoFile({ fileUrl: url}) ? 2 : 3
|
||||||
const fileData = {
|
const fileData = {
|
||||||
fileName: name,
|
fileName: name,
|
||||||
fileUrl: url,
|
fileUrl: url,
|
||||||
@ -413,7 +414,6 @@ const afterRead = async (options) => {
|
|||||||
}
|
}
|
||||||
if (!formData.value.fileList) formData.value.fileList = []
|
if (!formData.value.fileList) formData.value.fileList = []
|
||||||
formData.value.fileList.push(fileData)
|
formData.value.fileList.push(fileData)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(res.message)
|
throw new Error(res.message)
|
||||||
}
|
}
|
||||||
@ -431,14 +431,78 @@ const removeFile = (file, index) => {
|
|||||||
formData.value.fileList.splice(index, 1)
|
formData.value.fileList.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 暴露验证方法
|
// 简单的空值判断
|
||||||
|
const isEmpty = (value) => {
|
||||||
|
return value === null || value === undefined || value === ''
|
||||||
|
}
|
||||||
|
|
||||||
const validate = () => {
|
const validate = () => {
|
||||||
if (!formData.value.occurTime) {
|
if (isEmpty(formData.value.roadConditionType)) {
|
||||||
showToast('请填写发生时间')
|
showToast('请选择路况类别')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (!formData.value.routeNo) {
|
if (isEmpty(formData.value.event?.isBlocked)) {
|
||||||
showToast('请填写线路编号')
|
showToast('请选择是否阻断')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.repairProgress)) {
|
||||||
|
showToast('请选择抢险进度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.report?.disposalMeasures)) {
|
||||||
|
showToast('请选择处置措施')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.damageCount)) {
|
||||||
|
showToast('请输入水毁处数')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.blockedMileage)) {
|
||||||
|
showToast('请输入阻断里程')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.occurTime)) {
|
||||||
|
showToast('请选择发生时间')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.report?.expectRecoverTime)) {
|
||||||
|
showToast('请输入预计恢复时间')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.routeNo)) {
|
||||||
|
showToast('请输入线路编号')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.startStakeNo)) {
|
||||||
|
showToast('请输入起点桩号')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.endStakeNo)) {
|
||||||
|
showToast('请输入止点桩号')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.occurLocation)) {
|
||||||
|
showToast('请输入路况位置')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.blockedPointName)) {
|
||||||
|
showToast('请输入阻断点小地名')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.longitude)) {
|
||||||
|
showToast('请输入经度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.latitude)) {
|
||||||
|
showToast('请输入纬度')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (isEmpty(formData.value.event?.needsRecovery)) {
|
||||||
|
showToast('请选择是否需要恢复重建')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (formData.value.event?.needsRecovery && isEmpty(formData.value.event?.estimatedRecoveryCost)) {
|
||||||
|
showToast('请输入恢复重建预估费用')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -449,6 +513,110 @@ const getFormData = () => {
|
|||||||
return { ...formData.value }
|
return { ...formData.value }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提交表单
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
// 验证表单
|
||||||
|
if (!validate()) return
|
||||||
|
|
||||||
|
submitting.value = true
|
||||||
|
try {
|
||||||
|
// 获取表单数据
|
||||||
|
let formData = getFormData()
|
||||||
|
|
||||||
|
// 添加事件类型和站点信息
|
||||||
|
const submitData = {
|
||||||
|
...formData
|
||||||
|
// 可以在这里添加站点信息等其他数据
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await request({
|
||||||
|
url: '/snow-ops-platform/water-damage/addOrUpdate',
|
||||||
|
method: 'post',
|
||||||
|
data: submitData
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.code === '00000') {
|
||||||
|
showSuccessToast('提交成功')
|
||||||
|
let isRebuilded = false
|
||||||
|
if (isContinue && detail.value.event.needsRecovery) {
|
||||||
|
// 如果之前已经进行了项目重建的流程,后续不再进行该流程
|
||||||
|
isRebuilded = true
|
||||||
|
}
|
||||||
|
if (!isRebuilded && submitData.event.needsRecovery) {
|
||||||
|
router.replace({
|
||||||
|
name: 'RebuildAdd',
|
||||||
|
params: {
|
||||||
|
data: res.data.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 提交成功后返回列表页
|
||||||
|
setTimeout(() => {
|
||||||
|
router.replace('/disasterManagement')
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showFailToast(res.message)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
showFailToast('提交失败,请重试')
|
||||||
|
console.error('提交失败:', error)
|
||||||
|
} finally {
|
||||||
|
submitting.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const detail = ref(null)
|
||||||
|
|
||||||
|
// 获取灾毁详情
|
||||||
|
const getDisasterDetail = async () => {
|
||||||
|
const id = route.query.id
|
||||||
|
if (!id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await request({
|
||||||
|
url: `/snow-ops-platform/water-damage/getById`,
|
||||||
|
method: 'get',
|
||||||
|
params: { id }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (result?.data) {
|
||||||
|
// 接口返回 Data 结构
|
||||||
|
const data = result.data
|
||||||
|
detail.value = result.data
|
||||||
|
const newFormData = {
|
||||||
|
...data,
|
||||||
|
lossList: null,
|
||||||
|
report: route.query?.mock ? mockFormData : {},
|
||||||
|
fileList: null
|
||||||
|
}
|
||||||
|
initFormData(newFormData)
|
||||||
|
} else {
|
||||||
|
showToast(result.message || '获取详情失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取灾毁详情失败:', error)
|
||||||
|
showToast('获取详情失败,请稍后重试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日期格式化
|
||||||
|
const formatTime = (date = new Date()) => {
|
||||||
|
const pad = (n) => n.toString().padStart(2, '0')
|
||||||
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ` + `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
formData.value.occurTime = formatTime()
|
||||||
|
if (route.query.id) {
|
||||||
|
getDisasterDetail()
|
||||||
|
} else {
|
||||||
|
initFormData(route.query?.mock ? mockFormData : {})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 暴露方法给父组件
|
// 暴露方法给父组件
|
||||||
defineExpose({
|
defineExpose({
|
||||||
validate,
|
validate,
|
||||||
@ -543,4 +711,25 @@ defineExpose({
|
|||||||
width: 110px;
|
width: 110px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
.footer-btn {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 15px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
max-width: 340px;
|
||||||
|
border-radius: 48px;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: translateX(-50%) scale(0.98);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<CurrentSite />
|
<CurrentSite />
|
||||||
|
|
||||||
<!-- 基本信息 -->
|
<!-- 基本信息 -->
|
||||||
<PanelItem title="基本信息">
|
<PanelItem title="基本信息" v-if="!loading">
|
||||||
<template #headerExtra>
|
<template #headerExtra>
|
||||||
<div class="status-wrapper">
|
<div class="status-wrapper">
|
||||||
<van-tag :type="getEventStatusType()" size="medium" plain>
|
<van-tag :type="getEventStatusType()" size="medium" plain>
|
||||||
@ -140,7 +140,7 @@
|
|||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
<!-- 填报信息 -->
|
<!-- 填报信息 -->
|
||||||
<PanelItem title="填报信息">
|
<PanelItem title="填报信息" v-if="!loading">
|
||||||
<!-- 遍历所有填报记录(首报 + 续报) -->
|
<!-- 遍历所有填报记录(首报 + 续报) -->
|
||||||
<div v-for="(report, index) in allReports" :key="index" class="report-section">
|
<div v-for="(report, index) in allReports" :key="index" class="report-section">
|
||||||
<div class="report-header">
|
<div class="report-header">
|
||||||
@ -206,10 +206,12 @@
|
|||||||
</PanelItem>
|
</PanelItem>
|
||||||
|
|
||||||
<!-- 底部按钮:未解除状态显示续报按钮 -->
|
<!-- 底部按钮:未解除状态显示续报按钮 -->
|
||||||
<div class="footer-buttons">
|
<div class="footer-buttons" v-if="!loading">
|
||||||
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
|
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<van-loading class="loading-icon" v-if="loading">加载中...</van-loading>
|
||||||
|
|
||||||
<van-image-preview :startPosition="startPosition" v-model:show="previewImagesVisible" :images="imagesForPreview">
|
<van-image-preview :startPosition="startPosition" v-model:show="previewImagesVisible" :images="imagesForPreview">
|
||||||
<template v-slot:index="{ index }">第{{ index + 1 }}页</template>
|
<template v-slot:index="{ index }">第{{ index + 1 }}页</template>
|
||||||
</van-image-preview>
|
</van-image-preview>
|
||||||
@ -241,6 +243,8 @@ const detailData = ref({
|
|||||||
routeNo: ''
|
routeNo: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const loading = ref(true)
|
||||||
|
|
||||||
const allReports = computed(() => {
|
const allReports = computed(() => {
|
||||||
const reports =
|
const reports =
|
||||||
detailData.value.report?.map((item, index) => {
|
detailData.value.report?.map((item, index) => {
|
||||||
@ -314,6 +318,8 @@ const getDisasterDetail = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await request({
|
const result = await request({
|
||||||
url: `/snow-ops-platform/water-damage/getById`,
|
url: `/snow-ops-platform/water-damage/getById`,
|
||||||
@ -341,6 +347,7 @@ const getDisasterDetail = async () => {
|
|||||||
console.error('获取灾毁详情失败:', error)
|
console.error('获取灾毁详情失败:', error)
|
||||||
showToast('获取详情失败,请稍后重试')
|
showToast('获取详情失败,请稍后重试')
|
||||||
}
|
}
|
||||||
|
loading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击返回
|
// 点击返回
|
||||||
@ -524,4 +531,11 @@ onMounted(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -92,14 +92,14 @@ const gridItems = [
|
|||||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
icon: group106Icon,
|
// icon: group106Icon,
|
||||||
text: "冰雪灾害",
|
// text: "冰雪灾害",
|
||||||
to: {
|
// to: {
|
||||||
name: "IceEventManage",
|
// name: "IceEventManage",
|
||||||
params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
// params: { data: encodeURIComponent(JSON.stringify(yhzinfo.value)) },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
icon: group106Icon,
|
icon: group106Icon,
|
||||||
text: "灾害管理",
|
text: "灾害管理",
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="home">
|
<PageContainer title="冰雪灾害" @click-back="onClickLeft">
|
||||||
<van-nav-bar title="冰雪灾害" fixed left-arrow @click-left="onClickLeft" />
|
<CurrentSite />
|
||||||
|
|
||||||
<van-cell-group>
|
|
||||||
<van-cell title="当前站点" :value="yhzDetail.mc" />
|
|
||||||
</van-cell-group>
|
|
||||||
|
|
||||||
<div class="content" v-if="eventDetailData">
|
<div class="content" v-if="eventDetailData">
|
||||||
<van-cell-group>
|
<van-cell-group>
|
||||||
@ -276,19 +272,22 @@
|
|||||||
</van-button>
|
</van-button>
|
||||||
</div>
|
</div>
|
||||||
</van-popup>
|
</van-popup>
|
||||||
</div>
|
</PageContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, toRaw, reactive, watch, computed } from "vue";
|
import { ref, onMounted, toRaw, reactive, watch, computed } from "vue";
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
import { showToast, showLoadingToast, showImagePreview } from "vant";
|
import { showToast, showLoadingToast, showImagePreview } from "vant";
|
||||||
|
import PageContainer from '@/components/PageContainer.vue'
|
||||||
import { request } from "../../../../shared/utils/request";
|
import { request } from "../../../../shared/utils/request";
|
||||||
|
import CurrentSite from '@/components/CurrentSite.vue'
|
||||||
|
import { useYHZStore } from '@/stores/yhzStore';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const yhzStore = useYHZStore()
|
||||||
|
|
||||||
const yhzDetail = ref({});
|
|
||||||
const event = ref();
|
const event = ref();
|
||||||
const eventDetailData = ref(); // 冰雪事件详情数据
|
const eventDetailData = ref(); // 冰雪事件详情数据
|
||||||
|
|
||||||
@ -296,7 +295,7 @@ const eventDetailData = ref(); // 冰雪事件详情数据
|
|||||||
const getEventDetailData = async () => {
|
const getEventDetailData = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: `/snow-ops-platform/event/getById?id=${event.value.id}`,
|
url: `/snow-ops-platform/event/getById?id=${route.query.id}`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
if (res.code === "00000") {
|
if (res.code === "00000") {
|
||||||
@ -313,17 +312,11 @@ const getEventDetailData = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const data = JSON.parse(decodeURIComponent(route.params.data));
|
|
||||||
yhzDetail.value = data.yhzDetail;
|
|
||||||
event.value = data.event;
|
|
||||||
getEventDetailData();
|
getEventDetailData();
|
||||||
});
|
});
|
||||||
|
|
||||||
const onClickLeft = () => {
|
const onClickLeft = () => {
|
||||||
router.push({
|
router.replace('/disasterManagement')
|
||||||
name: "IceEventManage",
|
|
||||||
params: { data: encodeURIComponent(JSON.stringify(yhzDetail.value)) },
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showImage = (url) => {
|
const showImage = (url) => {
|
||||||
@ -574,7 +567,7 @@ const checkMaterialAmount = (material, index) => {
|
|||||||
const getMaterialList = async (wzmc) => {
|
const getMaterialList = async (wzmc) => {
|
||||||
try {
|
try {
|
||||||
const data = {
|
const data = {
|
||||||
yhzid: yhzDetail.value.id,
|
yhzid: yhzStore.getYHZInfo?.id,
|
||||||
wzmc,
|
wzmc,
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 9999,
|
pageSize: 9999,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user