feat: 水毁灾害

This commit is contained in:
niedongsheng 2026-04-10 14:55:19 +08:00
parent 2d3253ba0e
commit 145a0b1e33
7 changed files with 52 additions and 129 deletions

View File

@ -208,7 +208,7 @@
<script setup> <script setup>
import { onMounted, ref, computed } from 'vue' import { onMounted, ref, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { showToast } from 'vant' import { showToast, showImagePreview } from 'vant'
import PageContainer from '@/components/PageContainer.vue' import PageContainer from '@/components/PageContainer.vue'
import PanelItem from '@/components/PanelItem.vue' import PanelItem from '@/components/PanelItem.vue'
import CurrentSite from '@/components/CurrentSite.vue' import CurrentSite from '@/components/CurrentSite.vue'
@ -346,9 +346,8 @@ const handleContinueReport = () => {
// //
const previewFile = (file) => { const previewFile = (file) => {
if (file.fileUrl) { console.log("🚀 ~ previewFile ~ file:", file)
window.open(file.fileUrl, '_blank') // showImagePreview
}
} }
onMounted(() => { onMounted(() => {

View File

@ -9,14 +9,14 @@
</van-field> </van-field>
</template> </template>
<van-button size="small" block type="primary" plain @click="addLoss">添加损失</van-button> <van-button size="small" block type="primary" plain @click="addLoss">添加损失</van-button>
<CubeCalculateDialog ref="cubeCalculateDialog" @confirm="confirmCalculate" /> <CalculateDialog ref="cubeCalculateDialog" @confirm="confirmCalculate" />
<LossPicker ref="lossPicker" :options="options" @confirm="confirmAddLoss" /> <LossPicker ref="lossPicker" :options="options" @confirm="confirmAddLoss" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, computed, onMounted } from 'vue'
import CubeCalculateDialog from './CubeCalculateDialog.vue' import CalculateDialog from './CalculateDialog.vue'
import { request } from '@shared/utils/request' import { request } from '@shared/utils/request'
import LossPicker from './LossPicker.vue' import LossPicker from './LossPicker.vue'

View File

@ -130,7 +130,7 @@
<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/*" v-model="formData.fileList" :file-list="formData.fileList" :after-read="afterRead" multiple :max-count="6" /> <van-uploader accept="video/*,image/*" :modelValue="getFileList()" :after-read="afterRead" multiple :max-count="6" @delete="removeFile" />
</template> </template>
</van-field> </van-field>
</PanelItem> </PanelItem>
@ -148,7 +148,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, computed, watch } from 'vue' import { ref, computed, watch } 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'
@ -165,12 +165,8 @@ const isContinue = computed(() => route.query.isContinue)
// //
const disposalMeasureValue = ref('') const disposalMeasureValue = ref('')
// // - Request 使 ref
const imageFileList = ref([]) const formData = ref({
const videoFileList = ref([])
// - Request
const formData = reactive({
// //
occurLocation: '', // occurLocation: '', //
occurTime: '', // occurTime: '', //
@ -222,56 +218,12 @@ const formData = reactive({
// report.disposalMeasures // report.disposalMeasures
watch(disposalMeasureValue, (newVal) => { watch(disposalMeasureValue, (newVal) => {
formData.report.disposalMeasures = newVal formData.value.report.disposalMeasures = newVal
}) })
// fileList
watch(
imageFileList,
(newVal) => {
//
formData.fileList = [
...imageFileList.value.map((f) => ({
fileName: f.file?.name || '',
fileSize: f.file?.size || 0,
fileType: 1, // 1-
fileUrl: f.content || ''
})),
...videoFileList.value.map((f) => ({
fileName: f.file?.name || '',
fileSize: f.file?.size || 0,
fileType: 2, // 2-
fileUrl: f.content || ''
}))
]
},
{ deep: true }
)
watch(
videoFileList,
(newVal) => {
formData.fileList = [
...imageFileList.value.map((f) => ({
fileName: f.file?.name || '',
fileSize: f.file?.size || 0,
fileType: 1,
fileUrl: f.content || ''
})),
...newVal.map((f) => ({
fileName: f.file?.name || '',
fileSize: f.file?.size || 0,
fileType: 2,
fileUrl: f.content || ''
}))
]
},
{ deep: true }
)
// report.disposalMeasures // report.disposalMeasures
watch( watch(
() => formData.report.disposalMeasures, () => formData.value.report.disposalMeasures,
(newVal) => { (newVal) => {
if (newVal && typeof newVal === 'string') { if (newVal && typeof newVal === 'string') {
disposalMeasureValue.value = newVal disposalMeasureValue.value = newVal
@ -280,6 +232,17 @@ watch(
{ immediate: true } { immediate: true }
) )
const getFileList = () => {
const fileList = formData.value.fileList?.map((item) => {
return {
url: item.fileUrl,
name: item.fileName
}
})
return fileList
}
// BasePicker // BasePicker
const roadConditionOptions = [ const roadConditionOptions = [
{ label: '高速公路', value: '高速公路' }, { label: '高速公路', value: '高速公路' },
@ -312,19 +275,19 @@ const maxDate = new Date(2030, 11, 31)
const initFormData = (newVal) => { const initFormData = (newVal) => {
if (newVal && Object.keys(newVal).length > 0) { if (newVal && Object.keys(newVal).length > 0) {
// // -
Object.assign(formData, { formData.value = {
occurLocation: newVal.occurLocation || '', occurLocation: newVal.occurLocation || '',
occurTime: newVal.occurTime || '', occurTime: newVal.occurTime || '',
roadConditionType: newVal.roadConditionType || '', roadConditionType: newVal.roadConditionType || '',
routeNo: newVal.routeNo || '', routeNo: newVal.routeNo || '',
event: { ...formData.event, ...(newVal.event || {}) }, event: { ...formData.value.event, ...(newVal.event || {}) },
report: { ...formData.report, ...(newVal.report || {}) }, report: { ...formData.value.report, ...(newVal.report || {}) },
lossList: newVal.lossList || [], lossList: newVal.lossList || [],
fileList: newVal.fileList || [] fileList: newVal.fileList || []
}) }
// split //
if (newVal.report?.disposalMeasures) { if (newVal.report?.disposalMeasures) {
disposalMeasureValue.value = newVal.report.disposalMeasures disposalMeasureValue.value = newVal.report.disposalMeasures
} }
@ -335,11 +298,10 @@ const initFormData = (newVal) => {
const calibrateTime = () => { const calibrateTime = () => {
const now = new Date() 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')}` 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.occurTime = formatted formData.value.occurTime = formatted
showToast('时间已校准为当前时间') showToast('时间已校准为当前时间')
} }
// //
const afterImageRead = (file) => { const afterImageRead = (file) => {
console.log('图片上传:', file) console.log('图片上传:', file)
@ -425,7 +387,7 @@ const isValidVideo = (file) => {
} }
/** /**
* 统一的上传前校验用于 el-upload before-upload * 统一的上传前校验
* @param {File} file - 上传的文件 * @param {File} file - 上传的文件
* @returns {boolean} 是否允许上传 * @returns {boolean} 是否允许上传
*/ */
@ -446,19 +408,19 @@ const checkFile = (file) => {
const afterRead = async (options) => { const afterRead = async (options) => {
const file = options.file const file = options.file
if(!checkFile(file)) return if (!checkFile(file)) return
const toast = showLoadingToast({ const toast = showLoadingToast({
message: '上传中...', message: '上传中...',
forbidClick: true, forbidClick: true,
duration: 0 // 0 duration: 0 // 0
}) })
try { try {
const formData = new FormData() const uploadFormData = new FormData()
formData.append('file', file) uploadFormData.append('file', file)
const res = await request({ const res = await request({
url: '/snow-ops-platform/file/upload', url: '/snow-ops-platform/file/upload',
method: 'post', method: 'post',
data: formData data: uploadFormData
}) })
toast.close() toast.close()
if (res.code === '00000') { if (res.code === '00000') {
@ -472,10 +434,9 @@ const afterRead = async (options) => {
fileType: type, fileType: type,
fileSize: file.size fileSize: file.size
} }
if (!formData.fileList) formData.fileList = [] if (!formData.value.fileList) formData.value.fileList = []
formData.fileList.push(fileData) formData.value.fileList.push(fileData)
console.log('fileList.value', formData.fileList)
} else { } else {
throw new Error(res.message) throw new Error(res.message)
} }
@ -488,22 +449,27 @@ const afterRead = async (options) => {
} }
} }
const removeFile = (file, index) => {
//
formData.value.fileList.splice(index, 1)
}
// //
const validate = () => { const validate = () => {
if (!formData.occurTime) { if (!formData.value.occurTime) {
showToast('请填写发生时间') showToast('请填写发生时间')
return false return false
} }
if (!formData.routeNo) { if (!formData.value.routeNo) {
showToast('请填写线路编号') showToast('请填写线路编号')
return false return false
} }
return true return true
} }
// // - formData.value
const getFormData = () => { const getFormData = () => {
return { ...formData } return { ...formData.value }
} }
// //
@ -600,4 +566,4 @@ defineExpose({
width: 110px; width: 110px;
} }
} }
</style> </style>

View File

@ -1,42 +0,0 @@
[
{
"id": 1,
"title": "G242金铃乡老窖坪发生积雪",
"status": "未解除",
"occurTime": "2025/10/10 20:29",
"estimateRecoverTime": "2025/10/10 20:29",
"disasterType": "积雪"
},
{
"id": 2,
"title": "S521白鹿镇X发生边坡坍塌",
"status": "已解除",
"occurTime": "2025/10/10 20:29",
"estimateRecoverTime": "2025/10/10 20:29",
"disasterType": "边坡坍塌"
},
{
"id": 3,
"title": "彭水S523发生边坡坍塌",
"status": "未解除",
"occurTime": "2025/10/10 20:29",
"estimateRecoverTime": "2025/10/10 20:29",
"disasterType": "路基沉陷"
},
{
"id": 4,
"title": "梁平蟠龙镇G318发生山体滑坡",
"status": "已解除",
"occurTime": "2025/10/10 20:29",
"estimateRecoverTime": "2025/10/10 20:29",
"disasterType": "山体滑坡"
},
{
"id": 5,
"title": "重庆市大足区XX县G201行道树倒塌",
"status": "已解除",
"occurTime": "2025/10/10 20:29",
"estimateRecoverTime": "2025/10/10 20:29",
"disasterType": "行道树倒塌"
}
]

View File

@ -1,6 +1,6 @@
{ {
"occurLocation": "G108国道 K2250+300处", "occurLocation": "G108国道 K2250+300处",
"occurTime": "2024-07-15 14:30:00", "occurTime": null,
"roadConditionType": "国道", "roadConditionType": "国道",
"routeNo": "G108", "routeNo": "G108",
"event": { "event": {
@ -25,8 +25,8 @@
"deadCount": 0, "deadCount": 0,
"strandedVehicleCount": 12, "strandedVehicleCount": 12,
"disposalMeasures": "正常通行", "disposalMeasures": "正常通行",
"actualRecoverTime": "2024-07-17 12:00:00", "actualRecoverTime": null,
"expectRecoverTime": "2024-07-18 18:00:00", "expectRecoverTime": null,
"injuredCount": 1, "injuredCount": 1,
"investedFunds": 35.8, "investedFunds": 35.8,
"investedMachinery": 6, "investedMachinery": 6,

View File

@ -194,7 +194,7 @@ const routes = [
{ {
path: '/disasterManagement', path: '/disasterManagement',
name: 'disasterManagement', name: 'disasterManagement',
component: () => import('../views/DisasterManagement/DisasterManagement.vue'), component: () => import('../views/DisasterManagement/DisasterManagementPC.vue'),
meta: { meta: {
title: '灾害巡检事件', title: '灾害巡检事件',
breadcrumb: true breadcrumb: true
@ -203,7 +203,7 @@ const routes = [
{ {
path: '/disasterReport', path: '/disasterReport',
name: 'DisasterReport', name: 'DisasterReport',
component: () => import('../views/DisasterManagement/DisasterReport/DisasterReport.vue'), component: () => import('../views/DisasterManagement/DisasterReport/DisasterReportPC.vue'),
meta: { meta: {
title: '灾毁事件填报', title: '灾毁事件填报',
breadcrumb: true breadcrumb: true
@ -212,7 +212,7 @@ const routes = [
{ {
path: '/waterDisasterDetail', path: '/waterDisasterDetail',
name: 'WaterDisasterDetail', name: 'WaterDisasterDetail',
component: () => import('../views/DisasterManagement/DisasterDetail/WaterDisasterDetail.vue'), component: () => import('../views/DisasterManagement/DisasterDetail/WaterDisasterDetailPC.vue'),
meta: { meta: {
title: '水毁事件详情', title: '水毁事件详情',
breadcrumb: true breadcrumb: true