feat: 灾毁

This commit is contained in:
niedongsheng 2026-04-24 16:29:35 +08:00
parent 4ae4f080ca
commit f4d8e2a104
9 changed files with 161 additions and 59 deletions

View File

@ -29,9 +29,21 @@
<!-- 起点桩号 (event.startStakeNo) -->
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
<!-- 起点桩经度 -->
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="digit" />
<!-- 起点桩纬度 -->
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="digit" />
<!-- 止点桩号 (event.endStakeNo) -->
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
<!-- 止点桩经度 -->
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="digit" />
<!-- 止点桩纬度 -->
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="digit" />
<!-- 受灾里程 (event.disasterMileage) -->
<van-field
v-model="formData.event.disasterMileage"
@ -127,6 +139,8 @@
placeholder="请填写"
/>
<van-field v-model="formData.report.siteDescription" label="现场描述" placeholder="请填写" type="textarea" rows="2" autosize />
<BaseDatePicker
v-model="formData.report.actualRecoverTime"
label="实际恢复时间"
@ -152,15 +166,18 @@ import BasePicker from '@/components/BasePicker.vue';
import BaseDatePicker from '@/components/BaseDatePicker.vue';
import RoadRoutesPicker from '../components/RoadRoutesPicker.vue';
import MaterialPicker from '../components/MaterialPicker.vue';
import { useRoute } from 'vue-router';
import { request } from '@shared/utils/request';
import { useOptions } from '@shared/composables/useOptions';
import DisasterFileUpload from '../components/DisasterFileUpload.vue';
import { showToast, showFailToast, showLoadingToast, showSuccessToast } from 'vant';
import { useRouter, useRoute } from 'vue-router'
import { formatDate } from '@shared/utils';
import { useYHZStore } from '@/stores/yhzStore';
const route = useRoute();
const route = useRoute()
const router = useRouter()
const { options } = useOptions();
const yhzStore = useYHZStore();
//
const isContinue = computed(() => route.query.isContinue);
@ -169,7 +186,14 @@ const minDate = new Date();
const maxDate = new Date(2050, 11, 31);
const formData = ref({
event: {},
event: {
startStakeNo: '',
startStakeLng: '',
startStakeLat: '',
endStakeNo: '',
endStakeLng: '',
endStakeLat: '',
},
report: {},
fileList: [],
yhzMaterialList: [],
@ -205,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 ?? item.startpoint);
const endPoint = parsePointValue(item.endPoint ?? 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;
};
const calibrateTime = isShowToast => {
@ -239,18 +263,22 @@ const handleSubmit = async () => {
...formData.value,
//
};
submitData.event.serviceStationId = yhzStore.getYHZInfo?.id
submitData.event.serviceStationName = yhzStore.getYHZInfo?.mc
let apiUrl = formData.id ? '/snow-ops-platform/event/dispose' : '/snow-ops-platform/event/report'
let apiUrl = formData.value.event?.id ? '/snow-ops-platform/event/dispose' : '/snow-ops-platform/event/report'
if(formData.value.event?.id && formData.report.disposalMeasures == '正常通行') {
api = '/snow-ops-platform/event/release'
}
const res = await request({
url: apiUrl,
method: 'post',
data: submitData,
});
if (res?.code === '00000') {
showSuccessToast('提交成功');
let isRebuilded = false;
if (isContinue && detail.value.event.needsRecovery) {
if (isContinue.value && detail.value.event.needsRecovery) {
//
isRebuilded = true;
}
@ -264,7 +292,7 @@ const handleSubmit = async () => {
} else {
//
setTimeout(() => {
if (isContinue) router.go(-1);
if (isContinue.value) router.go(-1);
else router.replace('/disasterManagement');
}, 500);
}
@ -278,7 +306,7 @@ const handleSubmit = async () => {
submitting.value = false;
}
};
const detailData = ref(null);
const detail = ref(null);
const getDisasterDetail = async () => {
const id = route.query.id;
if (!id) {
@ -301,7 +329,7 @@ const getDisasterDetail = async () => {
data.report = {};
data.yhzMaterialList = [];
data.fileList = [];
detailData.value = data;
detail.value = data;
formData.value = data;
} else {
ElMessage.warning(result.message || '获取详情失败');

View File

@ -1,5 +1,5 @@
<template>
<PageContainer title="冰毁详情" @click-back="handleClickBack" class="page-container">
<PageContainer title="冰毁详情" @click-back="handleClickBack" class="page-container" :class="{ ['is-release'] : isRelease()}">
<!-- 当前站点信息 -->
<CurrentSite />
@ -136,7 +136,7 @@
</PanelItem>
<!-- 底部按钮未解除状态显示续报按钮 -->
<div class="footer-buttons" v-if="!loading">
<div class="footer-buttons" v-if="!loading && !isRelease()">
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
</div>
@ -196,12 +196,12 @@ const hasReportData = computed(() => {
//
const getEventStatusText = () => {
return detailData.eventStatus === 1 ? '已解除' : '未解除';
return isRelease() ? '已解除' : '未解除';
};
//
const getEventStatusType = () => {
return detailData.eventStatus === 1 ? 'success' : 'danger';
return isRelease() ? 'success' : 'danger';
};
//
@ -226,6 +226,11 @@ const getVehicleStrandedText = report => {
return count > 0 ? `有车滞留` : '无车滞留';
};
//
const isRelease = () => {
return detailData.value.report?.some(item => item.reportType == 3)
}
//
const getDisasterDetail = async () => {
const id = route.query.id;
@ -308,6 +313,10 @@ onMounted(() => {
<style scoped lang="scss">
.page-container {
padding-bottom: 80px;
&.is-release {
padding-bottom: 20px;
}
}
.status-wrapper {

View File

@ -35,9 +35,21 @@
<!-- 起点桩号 (event.startStakeNo) -->
<van-field v-model="formData.event.startStakeNo" label="起点桩号(K)" placeholder="请填写" />
<!-- 起点桩经度 -->
<van-field v-model="formData.event.startStakeLng" label="起点桩经度" placeholder="请填写" type="digit" />
<!-- 起点桩纬度 -->
<van-field v-model="formData.event.startStakeLat" label="起点桩纬度" placeholder="请填写" type="digit" />
<!-- 止点桩号 (event.endStakeNo) -->
<van-field v-model="formData.event.endStakeNo" label="止点桩号(K)" placeholder="请填写" />
<!-- 止点桩经度 -->
<van-field v-model="formData.event.endStakeLng" label="止点桩经度" placeholder="请填写" type="digit" />
<!-- 止点桩纬度 -->
<van-field v-model="formData.event.endStakeLat" label="止点桩纬度" placeholder="请填写" type="digit" />
<!-- 路况位置 (occurLocation) -->
<van-field v-model="formData.event.occurLocation" label="路况位置" placeholder="请填写" />
@ -160,16 +172,26 @@ import { useRouter, useRoute } from 'vue-router'
import { request } from '@shared/utils/request'
import { useOptions } from '@shared/composables/useOptions'
import { formatDate } from '@shared/utils'
import { useYHZStore } from '@/stores/yhzStore';
const route = useRoute()
const router = useRouter()
const { options } = useOptions()
const yhzStore = useYHZStore();
//
const isContinue = computed(() => route.query.isContinue)
// - Request 使 ref
const formData = ref({
// event
event: {},
event: {
startStakeNo: '',
startStakeLng: '',
startStakeLat: '',
endStakeNo: '',
endStakeLng: '',
endStakeLat: ''
},
// report
report: {},
@ -331,7 +353,14 @@ const handleSubmit = async () => {
...formData
//
}
let apiUrl = formData.id ? '/snow-ops-platform/water-damage/dispose' : '/snow-ops-platform/water-damage/report'
submitData.event.serviceStationId = yhzStore.getYHZInfo?.id
submitData.event.serviceStationName = yhzStore.getYHZInfo?.mc
//
let apiUrl = formData.value.event?.id ? '/snow-ops-platform/water-damage/dispose' : '/snow-ops-platform/water-damage/report'
if(formData.value.event?.id && formData.report.disposalMeasures == '正常通行') {
api = '/snow-ops-platform/water-damage/release'
}
const res = await request({
url: apiUrl,
method: 'post',
@ -341,7 +370,7 @@ const handleSubmit = async () => {
if (res?.code === '00000') {
showSuccessToast('提交成功')
let isRebuilded = false
if (isContinue && detail.value.event.needsRecovery) {
if (isContinue.value && detail.value.event.needsRecovery) {
//
isRebuilded = true
}
@ -355,7 +384,7 @@ const handleSubmit = async () => {
} else {
//
setTimeout(() => {
if(isContinue) router.go(-1)
if(isContinue.value) router.go(-1)
else router.replace('/disasterManagement')
}, 500)
}
@ -392,9 +421,9 @@ const getDisasterDetail = async () => {
detail.value = result.data
const newFormData = {
...data,
lossList: null,
lossList: [],
report: {},
fileList: null
fileList: []
}
initFormData(newFormData)
} else {
@ -408,7 +437,6 @@ const getDisasterDetail = async () => {
onMounted(() => {
console.log(formData.value)
formData.value.event.occurTime = formatDate(Date.now())
if (route.query.id) {
getDisasterDetail()

View File

@ -1,5 +1,5 @@
<template>
<PageContainer title="水毁详情" @click-back="handleClickBack" class="page-container">
<PageContainer title="水毁详情" @click-back="handleClickBack" class="page-container" :class="{ ['is-release'] : isRelease()}">
<!-- 当前站点信息 -->
<CurrentSite />
@ -160,7 +160,7 @@
<span class="info-label">有无车辆滞留</span>
<span class="info-value">{{ getVehicleStrandedText(report) }}</span>
</div>
<div class="info-row">
<div class="info-row" v-if="report.hasStrandedVehicles">
<span class="info-label">滞留车辆</span>
<span class="info-value">{{ report.strandedVehicleCount || 0 }}</span>
</div>
@ -200,7 +200,7 @@
</PanelItem>
<!-- 底部按钮未解除状态显示续报按钮 -->
<div class="footer-buttons" v-if="!loading">
<div class="footer-buttons" v-if="!loading && !isRelease()">
<van-button type="primary" class="footer-btn" @click="handleContinueReport">续报</van-button>
</div>
@ -249,6 +249,11 @@ const allReports = computed(() => {
// return reports.reverse()
})
//
const isRelease = () => {
return detailData.value.report?.some(item => item.reportType == 3)
}
//
const hasReportData = computed(() => {
return allReports.value.length > 0
@ -256,12 +261,12 @@ const hasReportData = computed(() => {
//
const getEventStatusText = () => {
return detailData.eventStatus === 1 ? '已解除' : '未解除'
return isRelease() ? '已解除' : '未解除'
}
//
const getEventStatusType = () => {
return detailData.eventStatus === 1 ? 'success' : 'danger'
return isRelease() ? 'success' : 'danger'
}
//
@ -374,6 +379,7 @@ const previewFile = (report, file) => {
previewImagesVisible.value = true
}
onMounted(() => {
getDisasterDetail()
})
@ -382,6 +388,10 @@ onMounted(() => {
<style scoped lang="scss">
.page-container {
padding-bottom: 80px;
&.is-release {
padding-bottom: 20px;
}
}
.status-wrapper {

View File

@ -134,7 +134,7 @@
<el-table-column label="操作" width="100" fixed="right" align="center">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="handleDetail(row)">详情</el-button>
<el-button link type="warning" size="small" @click="handleEdit(row)">编辑</el-button>
<el-button link type="warning" size="small" v-if="row.eventStatus == 0" @click="handleEdit(row)">编辑</el-button>
</template>
</el-table-column>
</el-table>

View File

@ -65,7 +65,7 @@
</el-select>
</el-form-item>
<el-form-item label="滞留车辆">
<el-form-item label="滞留车辆" v-if="formData.report.hasStrandedVehicles">
<NumberInput v-model="formData.report.strandedVehicleCount" :precision="0" placeholder="请填写" style="width: 300px">
<template #append></template>
</NumberInput>
@ -84,7 +84,8 @@
</BlockItem>
<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>
@ -100,6 +101,7 @@ import FileUpload from '@/component/FileUpload/FileUpload.vue'
import NumberInput from '@/component/NumberInput/NumberInput.vue'
import MaterialList from '../components/MaterialList.vue'
import { useOptions } from '@shared/composables/useOptions'
import { useRouter } from 'vue-router'
const props = defineProps({
value: {
@ -111,7 +113,7 @@ const props = defineProps({
const emit = defineEmits(['refresh'])
const { options } = useOptions()
const router = useRouter()
const formData = ref({})
@ -164,7 +166,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.value.event?.occurTime = `${year}-${month}-${day} ${hours}:${minutes}`
formData.value.event.occurTime = `${year}-${month}-${day} ${hours}:${minutes}`
ElMessage.success('时间已校准为当前时间')
}
@ -174,7 +176,7 @@ const handleHasStrandedVehiclesChange = (value) => {
}
}
const handleSubmit = async () => {
const handleAddSubmit = async () => {
if (!validate()) {
return
}
@ -198,6 +200,24 @@ const handleSubmit = async () => {
}
}
const handleCompleteSubmit = async () => {
const res = await request({
url: '/snow-ops-platform/event/release',
method: 'post',
data: {
...formData.value
}
})
if (res?.code === '00000') {
ElMessage.success('提交成功')
setTimeout(()=>{
router.replace({ path: '/iceDisasterDetail', query: { id: formData.value.event.id } })
}, 500)
} else {
ElMessage.error(res.message)
}
}
defineExpose({
validate,
initFormData,

View File

@ -60,6 +60,14 @@
<span class="info-label">起点桩号</span>
<span class="info-value">{{ formatStakeNo(detailData.event?.startStakeNo) }}</span>
</div>
<div class="info-item">
<span class="info-label">止点桩经度</span>
<span class="info-value">{{ formatValue(detailData.event?.startStakeLng) }}</span>
</div>
<div class="info-item">
<span class="info-label">止点桩纬度</span>
<span class="info-value">{{ formatValue(detailData.event?.startStakeLat ) }}</span>
</div>
</div>
<div class="stake-center">
<div class="info-item stake-mileage-item">
@ -77,12 +85,12 @@
<span class="info-value">{{ formatStakeNo(detailData.event?.endStakeNo) }}</span>
</div>
<div class="info-item">
<span class="info-label"></span>
<span class="info-value">{{ formatValue(detailData.event?.endStakeLat ?? detailData.event?.endStakeLatitude) }}</span>
<span class="info-label">止点桩经</span>
<span class="info-value">{{ formatValue(detailData.event?.endStakeLng) }}</span>
</div>
<div class="info-item">
<span class="info-label"></span>
<span class="info-value">{{ formatValue(detailData.event?.endStakeLng ?? detailData.event?.endStakeLongitude) }}</span>
<span class="info-label">止点桩纬</span>
<span class="info-value">{{ formatValue(detailData.event?.endStakeLat ) }}</span>
</div>
</div>
</el-row>
@ -117,11 +125,11 @@
</div>
<div class="info-item">
<span class="info-label">填报人</span>
<span class="info-value">{{ formatValue(report.reporterName || report.reportUserName || report.createByName) }}</span>
<span class="info-value">{{ formatValue(report.reporter) }}</span>
</div>
<div class="info-item">
<span class="info-label">联系电话</span>
<span class="info-value">{{ formatValue(report.reporterPhone || report.phone || report.reportPhone || report.contactPhone) }}</span>
<span class="info-value">{{ formatValue(report.contactPhone) }}</span>
</div>
<div class="info-item" v-for="(item, index) in report.materialUsageList" :key="index">
<span class="info-label">{{item.materialName}}</span>
@ -129,23 +137,23 @@
</div>
<div class="info-item">
<span class="info-label">投入资金</span>
<span class="info-value">{{ formatUnitValue(report.inputFunds ?? report.material?.inputFunds ?? report.investedFunds, '万元') }}</span>
<span class="info-value">{{ formatUnitValue(report.inputFunds , '万元') }}</span>
</div>
<div class="info-item">
<span class="info-label">投入人力</span>
<span class="info-value">{{ formatUnitValue(report.inputManpower ?? report.material?.inputManpower ?? report.investedManpower, '人次') }}</span>
<span class="info-value">{{ formatUnitValue(report.inputManpower , '人次') }}</span>
</div>
<div class="info-item">
<span class="info-label">投入设备</span>
<span class="info-value">{{ formatUnitValue(report.inputEquipment ?? report.material?.inputEquipment ?? report.investedMachinery, '台') }}</span>
<span class="info-value">{{ formatUnitValue(report.inputEquipment , '台') }}</span>
</div>
<div class="info-item">
<span class="info-label">有无车辆滞留</span>
<span class="info-value">{{ getHasStrandedVehiclesText(report) }}</span>
</div>
<div class="info-item">
<div class="info-item" v-if="report.hasStrandedVehicles">
<span class="info-label">滞留车辆</span>
<span class="info-value">{{ formatUnitValue(report.strandedVehicleCount ?? report.traffic?.strandedVehicleCount, '辆') }}</span>
<span class="info-value">{{ formatUnitValue(report.strandedVehicleCount, '辆') }}</span>
</div>
<div class="info-item">
<span class="info-label">现场情况描述</span>
@ -241,11 +249,11 @@ const getMaterialUsageText = (item) => {
}
const getHasStrandedVehiclesText = (report) => {
const value = report?.hasStrandedVehicles ?? report?.traffic?.hasStrandedVehicles
const value = report?.hasStrandedVehicles
if (value === 1 || value === true || value === '1' || value === '是' || value === '有') return '有'
if (value === 0 || value === false || value === '0' || value === '否' || value === '无') return '无'
const count = report?.strandedVehicleCount ?? report?.traffic?.strandedVehicleCount
const count = report?.strandedVehicleCount
if (count === null || count === undefined || count === '') return '-'
return Number(count) > 0 ? '有' : '无'
}

View File

@ -16,13 +16,13 @@
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系人员" prop="event.reporterName">
<el-input v-model="formData.event.reporterName" 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.reporterPhone">
<el-input v-model="formData.event.reporterPhone" 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,6 @@
</el-col>
<el-col :span="8">
<el-form-item label="填报站点" prop="event.serviceStationId">
{{ }}
<YHZSelect v-model="formData.event.serviceStationId" @change="(item) => formData.event.serviceStationName = item.mc" />
</el-form-item>
</el-col>
@ -213,7 +212,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-col :span="8" v-if="formData.report.hasStrandedVehicles">
<el-form-item label="滞留车辆" prop="report.strandedVehicleCount">
<NumberInput v-model="formData.report.strandedVehicleCount" :precision="0" placeholder="请填写" style="width: 100%">
<template #append></template>

View File

@ -58,8 +58,8 @@ export const useIceDisasterReport = () => {
const formData = reactive(createDefaultFormData())
const formRules = {
// 'event.reporterName': [{ required: true, message: '请输入联系人员', trigger: 'blur' }],
'event.reporterPhone': [
// 'report.contactPerson': [{ required: true, message: '请输入联系人员', trigger: 'blur' }],
'report.contactPhone': [
// { required: true, message: '请输入联系电话', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的联系电话', trigger: 'blur' }
],