feat: PC灾毁管理调整

This commit is contained in:
niedongsheng 2026-04-20 11:27:13 +08:00
parent 0badc69fa2
commit 238bd0de6d
11 changed files with 44 additions and 320 deletions

View File

@ -38,7 +38,7 @@
<el-col :xs="24" :sm="12" :md="8" :lg="6">
<el-form-item label="是否阻断">
<el-select v-model="filterForm.blocked" placeholder="请选择" clearable>
<el-option v-for="(option, idx) in options['yesNoBool']" :label="option.label" :value="option.value" :key="idx" />
<el-option v-for="(option, idx) in options['yesOrNoBool']" :label="option.label" :value="option.value" :key="idx" />
</el-select>
</el-form-item>
</el-col>

View File

@ -25,7 +25,6 @@
style="width: 100%"
/>
</el-form-item>
{{ formData.report.expectRecoverTime }}
<el-form-item label="实际预计恢复时间">
<el-date-picker

View File

@ -244,6 +244,7 @@ const formatUnitValue = (value, unit) => {
}
const getMaterialUsageText = (item) => {
if(item.usageAmount === null || item.usageAmount === undefined || item.usageAmount === '') return '-'
return item.usageAmount + ' ' + item.materialUnit
}

View File

@ -53,8 +53,11 @@
<BlockItem title="位置信息">
<el-row :gutter="24">
<el-col :span="8">
<!-- 路线类型并没有用于最终的表单提交而是作为线路编号的筛选条件存在-->
<el-form-item label="路线类型">
<el-input :model-value="routeTypeLabel" readonly />
<el-select v-model="filterForm.routeType" placeholder="请选择" style="width: 100%" @change="handleDistrictChange">
<el-option v-for="(option, idx) in options['roadType']" :key="idx" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
@ -205,7 +208,7 @@
<el-col :span="8">
<el-form-item label="有无滞留车辆" prop="report.hasStrandedVehicles">
<el-select v-model="formData.report.hasStrandedVehicles" placeholder="请选择" style="width: 100%" @change="handleHasStrandedVehiclesChange">
<el-option v-for="option in strandedVehicleOptions" :key="option.value" :label="option.label" :value="option.value" />
<el-option v-for="option in options['haveOrNot']" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
@ -230,8 +233,7 @@
<el-col :span="16">
<el-form-item label="附件上传" prop="fileList">
<div class="upload-wrapper">
<div class="upload-title">图片上传</div>
<FileUpload v-model="formData.fileList" type="image" :limit="9" />
<FileUpload v-model="formData.fileList" type="image" :limit="6" />
</div>
</el-form-item>
</el-col>
@ -268,21 +270,13 @@ const {
handleEventTypeChange,
handleRouteNoChange,
handleSubmit,
initFormData,
getFormData,
options,
routeTypeLabel,
strandedVehicleOptions,
submitting,
handleHasStrandedVehiclesChange,
validate
} = useIceDisasterReport()
defineExpose({
validate,
initFormData,
getFormData
})
</script>
<style scoped lang="scss">

View File

@ -3,84 +3,19 @@ import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { request } from '@/utils/request'
import { useOptions } from '@shared/composables/useOptions'
const DEFAULT_REPORTER_UNIT = '万州区公路中心'
import { useUserStore} from '@/store/userStore'
const createDefaultFormData = () => ({
occurLocation: '',
occurTime: '',
routeNo: '',
event: {
actualRecoverTime: '',
disasterMileage: null,
disposalMeasures: '',
district: '',
endStakeLat: null,
endStakeLng: null,
endStakeNo: '',
expectRecoverTime: '',
id: null,
occurLocation: '',
occurTime: '',
reporterName: '',
reporterPhone: '',
reportTime: '',
reportUnit: DEFAULT_REPORTER_UNIT,
roadConditionLocation: '',
routeNo: '',
routeType: '',
serviceStationId: '',
startStakeLat: null,
startStakeLng: null,
startStakeNo: ''
},
report: {
actualRecoverTime: '',
antiSlipSand: null,
disposalMeasures: '',
expectRecoverTime: '',
hasStrandedVehicles: null,
industrialSalt: null,
inputEquipment: null,
inputFunds: null,
inputManpower: null,
reporterName: '',
reporterPhone: '',
reportTime: '',
sandbags: null,
siteDescription: '',
strandedVehicleCount: null
},
event: {},
report: {},
fileList: [],
lossList: [],
yhzMaterialList: []
})
const mergeFormData = (source = {}) => {
const defaults = createDefaultFormData()
const merged = {
...defaults,
...source,
event: {
...defaults.event,
...(source.event || {})
},
report: {
...defaults.report,
...(source.report || {})
}
}
merged.fileList = Array.isArray(source.fileList) ? source.fileList : defaults.fileList
merged.lossList = Array.isArray(source.lossList) ? source.lossList : defaults.lossList
merged.yhzMaterialList = Array.isArray(source.yhzMaterialList) ? source.yhzMaterialList : defaults.yhzMaterialList
if (!merged.event.reportUnit) {
merged.event.reportUnit = DEFAULT_REPORTER_UNIT
}
return merged
}
const parsePointValue = (point) => {
if (!point) {
@ -114,6 +49,7 @@ const parsePointValue = (point) => {
export const useIceDisasterReport = () => {
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const { options, getAreaOptions } = useOptions()
const formRef = ref(null)
@ -123,15 +59,6 @@ export const useIceDisasterReport = () => {
routeType: ''
})
const formData = reactive(createDefaultFormData())
const strandedVehicleOptions = [
{ label: '有', value: 1 },
{ label: '无', value: 0 }
]
const routeTypeLabel = computed(() => {
const matched = options.value.roadType?.find((item) => item.value === filterForm.routeType)
return matched?.label || '国省道'
})
const formRules = {
'event.reporterName': [{ required: true, message: '请输入联系人员', trigger: 'blur' }],
@ -156,6 +83,7 @@ export const useIceDisasterReport = () => {
'report.siteDescription': [{ required: true, message: '请输入现场情况描述', trigger: 'blur' }],
fileList: [
{
required: true,
validator: (_rule, value, callback) => {
if (!Array.isArray(value) || value.length === 0) {
callback(new Error('请上传附件'))
@ -169,7 +97,7 @@ export const useIceDisasterReport = () => {
}
const initFormData = (data = {}) => {
Object.assign(formData, mergeFormData(data))
formData.event.reportUnit = userStore.userInfo?.organization?.orgName
}
const handleEventTypeChange = (value) => {
@ -221,33 +149,10 @@ export const useIceDisasterReport = () => {
}
const buildSubmitData = () => {
const payload = mergeFormData(formData)
const reportTime = payload.report.reportTime || payload.event.reportTime || getCurrentTime()
payload.event.routeNo = payload.routeNo
payload.event.occurTime = payload.occurTime
payload.event.reportTime = reportTime
payload.event.reportUnit = payload.event.reportUnit || DEFAULT_REPORTER_UNIT
payload.event.disposalMeasures = payload.report.disposalMeasures
payload.event.expectRecoverTime = payload.report.expectRecoverTime
payload.event.actualRecoverTime = payload.report.actualRecoverTime || null
payload.event.roadConditionLocation = payload.occurLocation
payload.event.routeType = filterForm.routeType
payload.event.eventType = eventType.value
payload.report.reporterName = payload.report.reporterName || payload.event.reporterName
payload.report.reporterPhone = payload.report.reporterPhone || payload.event.reporterPhone
payload.report.reportTime = reportTime
if (payload.report.hasStrandedVehicles !== 1) {
payload.report.strandedVehicleCount = null
}
return payload
console.log(formData)
return
}
const getFormData = () => buildSubmitData()
const validate = async () => {
if (!formRef.value) {
return false
@ -291,65 +196,6 @@ export const useIceDisasterReport = () => {
}
}
const getDisasterDetail = async () => {
if (!route.query.id) {
return
}
try {
const result = await request({
url: `/snow-ops-platform/event/getById?id=${route.query.id}`,
method: 'get'
})
if (result?.data) {
const data = result.data
const baseReport = data.report || data.reportList?.[data.reportList.length - 1] || {}
filterForm.routeType = data.event?.routeType || data.event?.roadType || filterForm.routeType
initFormData({
occurLocation: data.occurLocation || data.event?.roadConditionLocation || '',
occurTime: data.occurTime || data.event?.occurTime || '',
routeNo: data.routeNo || data.event?.routeNo || '',
event: {
...(data.event || {}),
reporterName: data.event?.reporterName || data.event?.contactPerson || '',
reporterPhone: data.event?.reporterPhone || data.event?.contactPhone || '',
reportUnit: data.event?.reportUnit || data.event?.reporterUnit || DEFAULT_REPORTER_UNIT,
startStakeLat: data.event?.startStakeLat ?? data.event?.startStakeLatitude ?? null,
startStakeLng: data.event?.startStakeLng ?? data.event?.startStakeLongitude ?? null,
endStakeLat: data.event?.endStakeLat ?? data.event?.endStakeLatitude ?? null,
endStakeLng: data.event?.endStakeLng ?? data.event?.endStakeLongitude ?? null
},
report: {
...baseReport,
disposalMeasures: baseReport.disposalMeasures || data.event?.disposalMeasures || '',
expectRecoverTime: baseReport.expectRecoverTime || data.event?.expectRecoverTime || '',
actualRecoverTime: baseReport.actualRecoverTime || data.event?.actualRecoverTime || '',
inputEquipment: baseReport.inputEquipment ?? data.material?.inputEquipment ?? baseReport.investedMachinery ?? null,
inputFunds: baseReport.inputFunds ?? data.material?.inputFunds ?? baseReport.investedFunds ?? null,
inputManpower: baseReport.inputManpower ?? data.material?.inputManpower ?? baseReport.investedManpower ?? null,
hasStrandedVehicles: baseReport.hasStrandedVehicles ?? data.traffic?.hasStrandedVehicles ?? null,
strandedVehicleCount: baseReport.strandedVehicleCount ?? data.traffic?.strandedVehicleCount ?? null,
industrialSalt: baseReport.industrialSalt ?? null,
antiSlipSand: baseReport.antiSlipSand ?? null,
sandbags: baseReport.sandbags ?? null,
reporterName: baseReport.reporterName || data.event?.reporterName || data.event?.contactPerson || '',
reporterPhone: baseReport.reporterPhone || data.event?.reporterPhone || data.event?.contactPhone || '',
reportTime: baseReport.reportTime || data.event?.reportTime || ''
},
fileList: data.fileList || [],
lossList: data.lossList || [],
yhzMaterialList: data.yhzMaterialList || baseReport.yhzMaterialList || []
})
} else {
ElMessage.warning(result?.message || '获取详情失败')
}
} catch (error) {
console.error('获取冰雪详情失败:', error)
ElMessage.error('获取详情失败,请稍后重试')
}
}
const handleBack = () => {
router.back()
}
@ -357,12 +203,7 @@ export const useIceDisasterReport = () => {
onMounted(async () => {
await getAreaOptions()
if (route.query.id) {
await getDisasterDetail()
return
}
initFormData({})
initFormData()
})
return {
@ -378,10 +219,7 @@ export const useIceDisasterReport = () => {
handleRouteNoChange,
handleSubmit,
initFormData,
getFormData,
options,
routeTypeLabel,
strandedVehicleOptions,
submitting,
validate
}

View File

@ -206,7 +206,6 @@ import ContinueReport from './WaterDisasterContinueReportPC.vue'
import { request } from '@shared/utils/request'
import LossListDetail from './WaterDisasterLossListDetailPC.vue'
import FileUpload from '@/component/FileUpload/FileUpload.vue'
import mockData from '../WaterDisasterReport/waterMockJson.json'
const route = useRoute()
@ -305,7 +304,7 @@ const getDisasterDetail = async () => {
const newFormData = {
...data,
lossList: null,
report: route.query.mock ? mockData.report : {},
report: {},
fileList: null
}
nextTick(() => {

View File

@ -4,7 +4,8 @@
<el-col :span="colSpan">
<div class="info-item">
<span class="info-label">{{ item.lossTypeName }}</span>
<span class="info-value">{{ getValue(item) }}{{ item.unit }}</span>
<span class="info-value" v-if="getValue(item)">{{ getValue(item) }}{{ item.unit }}</span>
<span class="info-value" v-else>-</span>
</div>
</el-col>
<el-col :span="colSpan" v-if="item.lossTypeCode == 'OTHER_LOSS'">
@ -39,13 +40,13 @@ const props = defineProps({
const getValue = (config) => {
const value = props.modelValue?.find((v) => v.lossTypeId === config.lossTypeId)
if (value == null) props.modelValue?.push({ ...config })
return value?.totalAmount || 0
return value?.totalAmount || null
}
const getRemark = (config) => {
const value = props.modelValue?.find((v) => v.lossTypeId === config.lossTypeId)
if (value == null) props.modelValue?.push({ ...config })
return value?.remark || ''
return value?.remark || '-'
}
const configs = ref([])

View File

@ -3,7 +3,7 @@
<template v-for="(item, index) in configs" :key="index">
<el-col :span="colSpan">
<el-form-item :label="item.lossTypeName">
<NumberInput :model-value="getValue(item)" :precision="2" @update:model-value="(value) => changeValue(item, value)">
<NumberInput :model-value="getValue(item)" placeholder="请填写" :precision="2" @update:model-value="(value) => changeValue(item, value)">
<template #append>{{ item.unit }}</template>
</NumberInput>
</el-form-item>
@ -36,7 +36,7 @@ const props = defineProps({
const getValue = (config) => {
const item = getValueItem(config)
return item?.totalAmount || 0
return item?.totalAmount || null
}
const getValueItem = (config) => {

View File

@ -67,7 +67,7 @@
<el-col :span="8">
<el-form-item label="是否阻断" prop="event.isBlocked">
<el-select v-model="formData.event.isBlocked" placeholder="请选择" style="width: 100%">
<el-option v-for="(option, idx) in options['yesNoBool']" :key="idx" :label="option.label" :value="option.value" />
<el-option v-for="(option, idx) in options['yesOrNoBool']" :key="idx" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
@ -94,8 +94,11 @@
<BlockItem title="位置信息">
<el-row :gutter="24">
<el-col :span="8">
<!-- 路线类型并没有用于最终的表单提交而是作为线路编号的筛选条件存在-->
<el-form-item label="路线类型">
<el-input :model-value="routeTypeLabel" readonly />
<el-select v-model="filterForm.routeType" placeholder="请选择" style="width: 100%" @change="handleDistrictChange">
<el-option v-for="(option, idx) in options['roadType']" :key="idx" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
@ -254,6 +257,16 @@
<BlockItem title="灾毁损失">
<LossList v-model:model-value="formData.lossList" />
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="损失总金额">
<NumberInput v-model="formData.report.totalLossAmount" :precision="2" placeholder="请填写(选填)" style="width: 300px">
<template #append>万元</template>
</NumberInput>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="投入机械" prop="report.investedMachinery">
@ -300,7 +313,7 @@
<el-col :span="8">
<el-form-item label="是否需要恢复重建" prop="event.needsRecovery">
<el-select v-model="formData.event.needsRecovery" placeholder="请选择" style="width: 100%">
<el-option v-for="(option, idx) in options['yesNoBool']" :key="idx" :label="option.label" :value="option.value" />
<el-option v-for="(option, idx) in options['yesOrNoBool']" :key="idx" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
</el-col>
@ -345,7 +358,6 @@ const {
handleRouteNoChange,
handleSubmit,
initFormData,
getFormData,
options,
routeTypeLabel,
showEstimatedRecoveryCost,
@ -353,11 +365,6 @@ const {
validate
} = useWaterDisasterReport()
defineExpose({
validate,
initFormData,
getFormData
})
</script>
<style scoped lang="scss">

View File

@ -3,9 +3,7 @@ import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { request } from '@/utils/request'
import { useOptions } from '@shared/composables/useOptions'
import mockData from './waterMockJson.json'
const DEFAULT_REPORTER_UNIT = '万州区公路中心'
import { useUserStore} from '@/store/userStore'
const createDefaultFormData = () => ({
occurLocation: '',
@ -13,81 +11,17 @@ const createDefaultFormData = () => ({
roadConditionType: '',
routeNo: '',
event: {
blockedMileage: null,
blockedPointName: '',
contactPerson: '',
contactPhone: '',
damageCount: null,
district: '',
endStakeLatitude: null,
endStakeLongitude: null,
endStakeNo: '',
estimatedRecoveryCost: null,
isBlocked: null,
latitude: null,
longitude: null,
needsRecovery: null,
repairProgress: '抢险中',
reportSite: '',
reporterUnit: DEFAULT_REPORTER_UNIT,
serviceStationId: '',
startStakeLatitude: null,
startStakeLongitude: null,
startStakeNo: ''
},
report: {
actualRecoverTime: '',
damagedVehicleCount: null,
deadCount: null,
disposalMeasures: '',
expectRecoverTime: '',
injuredCount: null,
investedFunds: null,
investedMachinery: null,
investedManpower: null,
remark: '',
siteDescription: '',
strandedPersonCount: null,
strandedVehicleCount: null,
totalLossAmount: null
},
lossList: [],
fileList: []
})
const mergeFormData = (source = {}) => {
const defaults = createDefaultFormData()
const merged = {
...defaults,
...source,
event: {
...defaults.event,
...(source.event || {})
},
report: {
...defaults.report,
...(source.report || {})
},
lossList: Array.isArray(source.lossList) ? source.lossList : defaults.lossList,
fileList: Array.isArray(source.fileList) ? source.fileList : defaults.fileList
}
if (!merged.event.reporterUnit) {
merged.event.reporterUnit = DEFAULT_REPORTER_UNIT
}
if (!merged.event.repairProgress) {
merged.event.repairProgress = '抢险中'
}
if (!merged.event.serviceStationId && merged.event.reportSite) {
merged.event.serviceStationId = merged.event.reportSite
}
return merged
}
export const useWaterDisasterReport = () => {
const router = useRouter()
const route = useRoute()
const userStore = useUserStore()
const { options, getAreaOptions } = useOptions()
const formRef = ref(null)
@ -146,7 +80,7 @@ export const useWaterDisasterReport = () => {
}
const initFormData = (data = {}) => {
Object.assign(formData, mergeFormData(data))
formData.event.reporterUnit = userStore.userInfo?.organization?.orgName
}
const handleEventTypeChange = (value) => {
@ -206,16 +140,8 @@ export const useWaterDisasterReport = () => {
}
const buildSubmitData = () => {
const payload = mergeFormData(formData)
if (!payload.event.reportSite && payload.event.serviceStationId) {
payload.event.reportSite = payload.event.serviceStationId
}
return payload
}
const getFormData = () => buildSubmitData()
const validate = async () => {
if (!formRef.value) {
return false
@ -267,7 +193,7 @@ export const useWaterDisasterReport = () => {
onMounted(async () => {
await getAreaOptions()
initFormData(route.query.mock ? mockData : {})
initFormData({})
})
return {
@ -282,7 +208,6 @@ export const useWaterDisasterReport = () => {
handleRouteNoChange,
handleSubmit,
initFormData,
getFormData,
options,
routeTypeLabel,
showEstimatedRecoveryCost,

View File

@ -1,40 +0,0 @@
{
"occurLocation": "G108国道 K2250+300处",
"occurTime": "2024-07-15 14:30:00",
"roadConditionType": "国道",
"routeNo": "G108",
"event": {
"blockedMileage": 1.5,
"blockedPointName": "磨盘山隧道口",
"contactPerson": "张明",
"contactPhone": "13812345678",
"damageCount": 3,
"district": "武侯区",
"endStakeNo": "K2251+200",
"estimatedRecoveryCost": 120.5,
"isBlocked": true,
"needsRecovery": true,
"repairProgress": "抢险中",
"reporterUnit": "武侯区交通运输局",
"startStakeNo": "K2250+300"
},
"report": {
"damagedVehicleCount": 2,
"strandedPersonCount": 12,
"deadCount": 0,
"strandedVehicleCount": 12,
"disposalMeasures": "全幅封闭",
"actualRecoverTime": "2024-07-17 12:00:00",
"expectRecoverTime": "2024-07-18 18:00:00",
"injuredCount": 1,
"investedFunds": 35.8,
"investedMachinery": 6,
"investedManpower": 45,
"remark": "已组织抢险队伍进行抢通,便道已修建完成",
"siteDescription": "因持续强降雨导致山体滑坡掩埋路面约50米边坡垮塌严重",
"totalLossAmount": 85.6
},
"lossList": [
],
"fileList": []
}