feat: 水毁灾害

This commit is contained in:
niedongsheng 2026-04-24 15:09:44 +08:00
parent 4520394ea3
commit 4ae4f080ca
13 changed files with 96 additions and 218 deletions

View File

@ -206,7 +206,7 @@ const handleClickItem = (item) => {
router.push({
path: '/waterDisasterDetail',
query: {
id: item.id
id: item.relationId
}
})
}

View File

@ -219,7 +219,7 @@ const handleRouteNoChange = (item = {}) => {
};
const calibrateTime = isShowToast => {
formData.value.event?.occurTime = formatDate(Date.now());
formData.value.event.occurTime = formatDate(Date.now());
if (isShowToast) showToast('时间已校准为当前时间');
};

View File

@ -40,7 +40,7 @@
<!-- 地点路线 -->
<div class="info-row">
<span class="info-label">路况位置</span>
<span class="info-value">{{ detailData.event?.occurLocation || '-' }}</span>
<span class="info-value">{{ detailData.event?.roadConditionLocation || '-' }}</span>
</div>
<!-- 发生地点 -->

View File

@ -1,8 +1,8 @@
<template>
<div class="water-disaster">
<div class="water-disaster" >
<!-- 基本信息 -->
<PanelItem title="基本信息" v-if="!isContinue">
<van-form>
<van-form >
<!-- 路况类别 -->
<BasePicker v-model="formData.event.roadConditionType" :options="options['waterRoadConditionType']" label="路况类别" placeholder="请选择" />
@ -23,14 +23,14 @@
</van-field>
<!-- 发生时间 (顶层 occurTime) -->
<BaseDatePicker v-model="formData.event?.occurTime" label="发生时间" placeholder="请选择时间" :columnsType="['year', 'month', 'day', 'hour', 'minute']" />
<BaseDatePicker v-model="formData.event.occurTime" label="发生时间" placeholder="请选择时间" :columnsType="['year', 'month', 'day', 'hour', 'minute']" />
<div class="calibrate-time-btn" @click="calibrateTime">
<van-icon name="replay" />
<span>校准时间</span>
</div>
<!-- 线路编号 (顶层 routeNo) -->
<RoadRoutesPicker v-model="formData.event?.routeNo" label="线路编号" placeholder="请线路" @change="handleRouteNoChange" />
<RoadRoutesPicker v-model="formData.event.routeNo" label="线路编号" placeholder="请线路" @change="handleRouteNoChange" />
<!-- 起点桩号 (event.startStakeNo) -->
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
@ -38,12 +38,8 @@
<!-- 止点桩号 (event.endStakeNo) -->
<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) -->
<van-field v-model="formData.event?.occurLocation" label="路况位置" placeholder="请填写" />
<van-field v-model="formData.event.occurLocation" label="路况位置" placeholder="请填写" />
<!-- 阻断点小地名 (event.blockedPointName) -->
<van-field v-model="formData.event.blockedPointName" label="阻断点小地名" placeholder="请填写" />
@ -173,43 +169,10 @@ const isContinue = computed(() => route.query.isContinue)
// - Request 使 ref
const formData = ref({
// event
event: {
occurLocation: '', // /
occurTime: null, //
routeNo: '', // 线
roadConditionType: '', //
blockedMileage: '', //
blockedPointName: '', //
contactPerson: '', //
contactPhone: '', //
damageCount: '', //
district: '', //
endStakeNo: '', //
estimatedRecoveryCost: '', //
isBlocked: '', //
needsRecovery: '', //
repairProgress: '', //
reporterUnit: '', //
startStakeNo: '' //
},
event: {},
// report
report: {
actualRecoverTime: '', //
damagedVehicleCount: '', //
deadCount: '', //
disposalMeasures: '', //
expectRecoverTime: '', //
injuredCount: '', //
investedFunds: '', //
investedMachinery: '', //
investedManpower: '', //
remark: '', // /
siteDescription: '', //
strandedPersonCount: '', //
strandedVehicleCount: '', //
totalLossAmount: '' //
},
report: {},
// lossList
lossList: [],
@ -225,22 +188,14 @@ const minDate = new Date(2020, 0, 1)
const maxDate = new Date(2030, 11, 31)
const initFormData = (newVal) => {
if (newVal && Object.keys(newVal).length > 0) {
// -
formData.value = {
event: { ...formData.value.event, ...(newVal.event || {}) },
report: { ...formData.value.report, ...(newVal.report || {}) },
lossList: newVal.lossList || [],
fileList: newVal.fileList || []
}
}
formData.value = { ...newVal }
}
//
const calibrateTime = () => {
const now = new Date()
const formatted = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`
formData.value.event?.occurTime = formatted
formData.value.event.occurTime = formatted
showToast('时间已校准为当前时间')
}
@ -274,17 +229,17 @@ const parsePointValue = (point) => {
}
const handleRouteNoChange = (item) => {
formData.event.routeNo = item.routeCode
formData.event.startStakeNo = item.startStakeNo
formData.event.endStakeNo = item.endStakeNo
formData.value.event.routeNo = item.routeCode
formData.value.event.startStakeNo = item.startStakeNo
formData.value.event.endStakeNo = item.endStakeNo
const startPoint = parsePointValue(item.startPoint)
const endPoint = parsePointValue(item.endPoint)
formData.event.startStakeLng = startPoint.longitude
formData.event.startStakeLat = startPoint.latitude
formData.event.endStakeLng = endPoint.longitude
formData.event.endStakeLat = endPoint.latitude
formData.value.event.startStakeLng = startPoint.longitude
formData.value.event.startStakeLat = startPoint.latitude
formData.value.event.endStakeLng = endPoint.longitude
formData.value.event.endStakeLat = endPoint.latitude
}
//
@ -453,12 +408,11 @@ const getDisasterDetail = async () => {
onMounted(() => {
formData.value.event?.occurTime = formatDate(Date.now())
console.log(formData.value)
formData.value.event.occurTime = formatDate(Date.now())
if (route.query.id) {
getDisasterDetail()
} else {
initFormData({})
}
}
})
//

View File

@ -330,7 +330,7 @@ const handleDetail = (row) => {
//
const handleEdit = (row) => {
if (row.disasterType == 'WATER_DAMAGE') {
router.push({ path: '/waterDisasterDetail', query: { id: row.id, mode: 'edit' } })
router.push({ path: '/waterDisasterDetail', query: { id: row.relationId, mode: 'edit' } })
}
if (row.disasterType == 'ICE_SNOW') {
router.push({ path: '/iceDisasterDetail', query: { id: row.relationId, mode: 'edit' } })

View File

@ -40,7 +40,7 @@
<el-col :span="8">
<div class="info-item">
<span class="info-label">路况位置</span>
<span class="info-value">{{ detailData.event?.occurLocation || '-' }}</span>
<span class="info-value">{{ detailData.event?.roadConditionLocation || '-' }}</span>
</div>
</el-col>
<el-col :span="8">

View File

@ -39,7 +39,8 @@
</el-col>
<el-col :span="8">
<el-form-item label="填报站点" prop="event.serviceStationId">
<YHZSelect v-model="formData.event.serviceStationId" />
{{ }}
<YHZSelect v-model="formData.event.serviceStationId" @change="(item) => formData.event.serviceStationName = item.mc" />
</el-form-item>
</el-col>
<el-col :span="8">
@ -81,8 +82,8 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="路况位置" prop="occurLocation">
<el-input v-model="formData.occurLocation" placeholder="请选择">
<el-form-item label="路况位置" prop="event.roadConditionLocation">
<el-input v-model="formData.event.roadConditionLocation" placeholder="请选择">
<template #suffix>
<el-icon class="location-icon"><LocationFilled /></el-icon>
</template>

View File

@ -68,7 +68,7 @@ export const useIceDisasterReport = () => {
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
'event.occurLocation': [{ required: true, message: '请输入发生地点', trigger: 'blur' }],
occurLocation: [{ required: true, message: '请选择路况位置', trigger: 'blur' }],
'event.roadConditionLocation': [{ required: true, message: '请输入路况位置', trigger: 'blur' }],
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],
'event.startStakeLat': [{ required: true, message: '请输入起点桩纬度', trigger: 'blur' }],

View File

@ -84,7 +84,7 @@
</el-form-item>
<!-- 损失列表组件 -->
<loss-list :col-span="24" v-model="formData.lossList" />
<loss-list :col-span="24" v-if="formData.lossList" v-model="formData.lossList" />
<!-- 已投机械 -->
<el-form-item label="投入机械">
@ -133,7 +133,8 @@
</el-form-item> -->
<el-form-item>
<el-button type="primary" @click="handleSubmit">追加记录</el-button>
<el-button type="primary" @click="handleAddSubmit">追加记录</el-button>
<el-button type="primary" @click="handleCompleteSubmit">解除事件</el-button>
</el-form-item>
</el-form>
</el-card>
@ -141,12 +142,13 @@
</template>
<script setup>
import { ref, reactive, watch, computed } from 'vue'
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { request } from '@shared/utils/request'
import BlockItem from '@/component/BlockItem.vue'
import NumberInput from '@/component/NumberInput/NumberInput.vue'
import LossList from '../WaterDisasterReport/WaterDisasterLossListPC.vue'
import { useRouter } from 'vue-router'
// Props
const props = defineProps({
@ -159,49 +161,19 @@ const props = defineProps({
// Emits
const emit = defineEmits(['input', 'change'])
//
const formData = reactive({
const router = useRouter()
const createDefaultFormData = () => ({
event: {
occurLocation: '',
occurTime: '',
roadConditionType: '',
routeNo: '',
blockedMileage: '',
blockedPointName: '',
contactPerson: '',
contactPhone: '',
damageCount: '',
district: '',
endStakeNo: '',
estimatedRecoveryCost: '',
isBlocked: '',
needsRecovery: '',
repairProgress: '',
reporterUnit: '',
startStakeNo: ''
},
report: {
actualRecoverTime: '',
damagedVehicleCount: '',
deadCount: '',
disposalMeasures: '',
expectRecoverTime: '',
injuredCount: '',
investedFunds: '',
investedMachinery: '',
investedManpower: '',
remark: '',
siteDescription: '',
strandedPersonCount: '',
strandedVehicleCount: '',
totalLossAmount: ''
},
lossList: [],
fileList: []
})
//
const disposalMeasureValue = ref('')
//
const formData = ref(createDefaultFormData())
//
const roadConditionOptions = [
@ -231,11 +203,6 @@ const pickerOptions = {
}
}
//
watch(disposalMeasureValue, (newVal) => {
formData.report.disposalMeasures = newVal
})
//
watch(
() => props.value,
@ -249,7 +216,7 @@ watch(
//
watch(
() => formData,
formData,
(newVal) => {
emit('input', newVal)
emit('change', newVal)
@ -257,29 +224,9 @@ watch(
{ deep: true }
)
// report.disposalMeasures
watch(
() => formData.report.disposalMeasures,
(newVal) => {
if (newVal && typeof newVal === 'string') {
disposalMeasureValue.value = newVal
}
},
{ immediate: true }
)
//
const initFormData = (data) => {
Object.assign(formData, {
event: { ...formData.event, ...(data.event || {}) },
report: { ...formData.report, ...(data.report || {}) },
lossList: data.lossList || [],
fileList: data.fileList || []
})
if (data.report?.disposalMeasures) {
disposalMeasureValue.value = data.report.disposalMeasures
}
formData.value = data
}
//
@ -290,7 +237,7 @@ const calibrateTime = () => {
const day = String(now.getDate()).padStart(2, '0')
const hours = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0')
formData.event?.occurTime = `${year}-${month}-${day} ${hours}:${minutes}`
formData.value.event.occurTime = `${year}-${month}-${day} ${hours}:${minutes}`
ElMessage.success('时间已校准为当前时间')
}
@ -301,54 +248,17 @@ const validate = () => {
//
const getFormData = () => {
return { ...formData }
return {
...formData.value,
}
}
//
const resetForm = () => {
Object.assign(formData, {
event: {
occurLocation: '',
occurTime: '',
roadConditionType: '',
routeNo: '',
blockedMileage: '',
blockedPointName: '',
contactPerson: '',
contactPhone: '',
damageCount: '',
district: '',
endStakeNo: '',
estimatedRecoveryCost: '',
isBlocked: '',
needsRecovery: '',
repairProgress: '',
reporterUnit: '',
startStakeNo: ''
},
report: {
actualRecoverTime: '',
damagedVehicleCount: '',
deadCount: '',
disposalMeasures: '',
expectRecoverTime: '',
injuredCount: '',
investedFunds: '',
investedMachinery: '',
investedManpower: '',
remark: '',
siteDescription: '',
strandedPersonCount: '',
strandedVehicleCount: '',
totalLossAmount: ''
},
lossList: [],
fileList: []
})
disposalMeasureValue.value = ''
formData.value = createDefaultFormData()
}
const handleSubmit = async () => {
const handleAddSubmit = async () => {
//
if (!validate()) {
return
@ -359,7 +269,7 @@ const handleSubmit = async () => {
//
const submitData = {
...formData
...formData.value
//
}
@ -383,6 +293,24 @@ const handleSubmit = 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({
validate,

View File

@ -12,7 +12,7 @@
<div class="base-info-group">
<el-row v-for="(row, rowIndex) in baseInfoRows" :key="rowIndex" :gutter="24" class="base-info-row">
<el-col v-for="item in row" :key="`${rowIndex}-${item.label}`" :span="getColSpan(row)" class="info-column">
<el-col v-for="item in row" :key="`${rowIndex}-${item.label}`" :span="getColSpan(item, row)" class="info-column">
<div class="info-item">
<span class="info-label">{{ item.label }}</span>
<span class="info-value">{{ item.value }}</span>
@ -38,16 +38,14 @@
</div>
<div class="content-wrapper">
<div class="basic-info-wrapper">
<div class="report-info-group">
<el-row v-for="(row, rowIndex) in getReportInfoRows(report)" :key="rowIndex" :gutter="24" class="report-info-row">
<el-col v-for="item in row" :key="`${rowIndex}-${item.label}`" :span="getColSpan(row)" class="info-column">
<div class="info-item">
<span class="info-label">{{ item.label }}</span>
<span class="info-value">{{ item.value }}</span>
</div>
</el-col>
</el-row>
</div>
<el-row :gutter="24" class="report-info-row">
<el-col v-for="item in getReportInfoItems(report)" :key="item.label" :span="24" class="info-column">
<div class="info-item">
<span class="info-label">{{ item.label }}</span>
<span class="info-value">{{ item.value }}</span>
</div>
</el-col>
</el-row>
<div class="file-list">
<FileUpload v-model="report.fileList" :readonly="!isEdit" />
</div>
@ -162,38 +160,35 @@ const baseInfoRows = computed(() => {
{ label: '止点桩号', value: detailData.value.event?.endStakeNo || '-' },
],
[
{ label: '路况位置', value: detailData.value.occurLocation || '-' },
{ label: '路况位置', value: detailData.value.event?.occurLocation || '-' },
{ label: '阻断点小地名', value: detailData.value.event?.blockedPointName || '-' },
{ label: '所属区县', value: detailData.value.event?.district || '-' },
],
[
{ label: '是否需要恢复重建', value: formatBooleanValue(detailData.value.event?.needsRecovery) }
{ label: '是否需要恢复重建', value: formatBooleanValue(detailData.value.event?.needsRecovery), span: 8 }
],
]
if (detailData.value.event?.estimatedRecoveryCost) {
rows[4].push([{ label: '恢复重建预估费用(万元)', value: detailData.value.event?.estimatedRecoveryCost ?? '-' }])
rows[5].push({ label: '恢复重建预估费用(万元)', value: detailData.value.event?.estimatedRecoveryCost ?? '-', span: 16 })
}
return rows
})
const getReportInfoRows = (report) => {
const getReportInfoItems = (report) => {
return [
[{ label: '现场描述', value: report.siteDescription || '-' }],
[{ label: '处置措施', value: report.disposalMeasures || '-' }],
[
{ label: '实际恢复时间', value: report.actualRecoverTime || '-' },
{ label: '预计恢复时间', value: report.expectRecoverTime || '-' }
],
[
{ label: '填报人', value: report.reporterName || '-' },
{ label: '联系电话', value: report.phone || '-' }
]
{ label: '现场描述', value: report.siteDescription || '-' },
{ label: '处置措施', value: report.disposalMeasures || '-' },
{ label: '实际恢复时间', value: report.actualRecoverTime || '-' },
{ label: '预计恢复时间', value: report.expectRecoverTime || '-' },
{ label: '填报人', value: report.reporterName || '-' },
{ label: '联系电话', value: report.phone || '-' }
]
}
const getColSpan = (row) => {
const getColSpan = (item, row) => {
if(item.span) return item.span
const length = row?.length || 1
return Math.floor(24 / length)
}
@ -336,7 +331,6 @@ onMounted(() => {
}
.base-info-group,
.report-info-group,
.base-info-row,
.report-info-row {
width: 100%;

View File

@ -16,13 +16,13 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系人员" prop="event.contactPerson">
<el-input v-model="formData.event.contactPerson" placeholder="请填写" />
<el-form-item label="联系人员" prop="report.contactPerson">
<el-input v-model="formData.report.contactPerson" placeholder="请填写" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系电话" prop="event.contactPhone">
<el-input v-model="formData.event.contactPhone" maxlength="11" placeholder="请填写" />
<el-form-item label="联系电话" prop="report.contactPhone">
<el-input v-model="formData.report.contactPhone" maxlength="11" placeholder="请填写" />
</el-form-item>
</el-col>
</el-row>
@ -39,7 +39,7 @@
</el-col>
<el-col :span="8">
<el-form-item label="填报站点" prop="event.serviceStationId">
<YHZSelect v-model="formData.event.serviceStationId" />
<YHZSelect v-model="formData.event.serviceStationId" @change="(item) => formData.event.serviceStationName = item.mc" />
</el-form-item>
</el-col>
<el-col :span="8">

View File

@ -36,8 +36,8 @@ export const useWaterDisasterReport = () => {
const showEstimatedRecoveryCost = computed(() => formData.event.needsRecovery === true)
const formRules = {
// 'event.contactPerson': [{ required: true, message: '请输入联系人员', trigger: 'blur' }],
'event.contactPhone': [
// 'report.contactPerson': [{ required: true, message: '请输入联系人员', trigger: 'blur' }],
'report.contactPhone': [
// { required: true, message: '请输入联系电话', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的联系电话', trigger: 'blur' }
],
@ -50,7 +50,7 @@ export const useWaterDisasterReport = () => {
'event.damageCount': [{ required: true, message: '请输入水毁处数', trigger: 'blur' }],
'event.district': [{ required: true, message: '请选择所属区县', trigger: 'change' }],
'event.routeNo': [{ required: true, message: '请选择线路编号', trigger: 'change' }],
occurLocation: [{ required: true, message: '请输入路况位置', trigger: 'blur' }],
'event.occurLocation': [{ required: true, message: '请输入路况位置', trigger: 'blur' }],
'event.blockedPointName': [{ required: true, message: '请输入阻断点小地名', trigger: 'blur' }],
'event.startStakeNo': [{ required: true, message: '请输入起点桩号', trigger: 'blur' }],
'event.startStakeLng': [{ required: true, message: '请输入起点桩经度', trigger: 'blur' }],

View File

@ -213,6 +213,7 @@ const handleSizeChange = (size) => {
const handleRowClick = (row) => {
tempSelectedItem.value = row
console.log("🚀 ~ handleRowClick ~ row:", row)
selectedValue.value = tempSelectedItem.value.id
dialogVisible.value = false
emit('change', tempSelectedItem.value)