260 lines
9.7 KiB
Vue
Raw Normal View History

2026-04-07 15:12:09 +08:00
<template>
<PageContainer title="项目填报" @click-back="handleClickBack">
<div class="content">
2026-04-07 16:29:39 +08:00
<PanelItem>
2026-04-09 11:35:50 +08:00
<van-form ref="formRef" label-align="left" colon>
<van-field v-model="form.project.districtName" label="区县名称" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写区县名称' }]" />
<RoadRoutesPicker v-model="form.project.routeNo" label="线路编号" center placeholder="请选择" required
:rules="[{ required: true, message: '请选择线路编号' }]" @change="handleRouteNoChange" />
2026-04-15 11:48:35 +08:00
<van-field v-model="form.project.startStakeNo" label="起点桩号" disabled center placeholder="请选择线路编号"
required :rules="[{ required: true, message: '请填写起点桩号' }]" />
<van-field v-model="form.project.endStakeNo" label="止点桩号" disabled center placeholder="请选择线路编号"
required :rules="[{ required: true, message: '请填写止点桩号' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.implementMileage" label="实施里程" center placeholder="单位:公里" required
type="number" :rules="[{ required: true, message: '请填写实施里程' }]">
2026-04-07 16:29:39 +08:00
<template #extra>
公里
</template>
</van-field>
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.earthworkLoss" label="塌方及损失" center placeholder="(方/万元)" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写塌方及损失' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.disasterType" label="灾害类型" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写灾害类型' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.locationRoute" label="地点路线" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写地点路线' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.roadLocation" label="路况位置" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写路况位置' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.blockedPointName" label="阻断点小地名" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写阻断点小地名' }]" />
2026-04-09 11:35:50 +08:00
<van-field v-model="form.project.estimatedCost" label="恢复重建预估费用" center placeholder="请填写" required
2026-04-07 16:29:39 +08:00
:rules="[{ required: true, message: '请填写恢复重建预估费用' }]">
<template #extra>
万元
</template>
</van-field>
<van-field label="附件" center>
<template #input>
2026-04-09 11:35:50 +08:00
<van-uploader v-model="fileList" @delete="handleDelete" name="files" :file-list="fileList"
accept=".png,.jpg,.mp4" :after-read="afterRead" multiple :max-count="6" />
2026-04-07 16:29:39 +08:00
</template>
</van-field>
</van-form>
</PanelItem>
2026-04-07 15:12:09 +08:00
</div>
<van-button type="primary" class="add-btn" icon="plus" @click="handleAdd">
提交
</van-button>
</PageContainer>
</template>
<script setup>
2026-04-09 11:35:50 +08:00
import { ref, onMounted, watch, reactive, toRaw } from 'vue'
2026-04-07 15:12:09 +08:00
import { useRouter, useRoute } from 'vue-router'
import PageContainer from '@/components/PageContainer.vue'
2026-04-07 16:29:39 +08:00
import { showToast, showLoadingToast } from "vant";
import PanelItem from '@/components/PanelItem.vue'
2026-04-09 11:35:50 +08:00
import { request } from "../../../../shared/utils/request";
import RoadRoutesPicker from '../DisasterManagement/RoadRoutesPicker.vue'
2026-04-07 15:12:09 +08:00
const router = useRouter()
const route = useRoute()
2026-04-09 11:35:50 +08:00
const form = reactive({
project: {
districtName: null,
routeNo: null,
startStakeNo: null,
endStakeNo: null,
implementMileage: null,
earthworkLoss: null,
disasterType: null,
locationRoute: null,
roadLocation: null,
blockedPointName: null,
estimatedCost: null,
},
fileList: []
})
2026-04-07 16:29:39 +08:00
const fileList = ref([]);
2026-04-09 11:35:50 +08:00
const formRef = ref();
2026-04-07 16:29:39 +08:00
2026-04-15 11:48:35 +08:00
// 获取灾害事件详情
const getDetail = async (id) => {
try {
const res = await request({
url: '/snow-ops-platform/water-damage/getById',
method: 'GET',
params: {
id
}
})
if (res.code === '00000') {
form.project.districtName = res.data.event.district
form.project.routeNo = res.data.routeNo
form.project.startStakeNo = res.data.event.startStakeNo
form.project.endStakeNo = res.data.event.endStakeNo
form.project.implementMileage = res.data.event.blockedMileage
form.project.earthworkLoss = Array.isArray(res.data.lossList) ? res.data.lossList.reduce((sum, item) => sum + (item.totalAmount || 0), 0) : 0
form.project.disasterType = res.data.roadConditionType
form.project.locationRoute = res.data.occurLocation
form.project.roadLocation = res.data.event.blockedPointName
form.project.blockedPointName = res.data.event.blockedPointName
form.project.estimatedCost = res.data.event.estimatedRecoveryCost
form.fileList = res.data.fileList || []
fileList.value = res.data.fileList || []
} else {
throw new Error(res.message)
}
} catch (error) {
showToast({
type: "fail",
message: error.message,
});
}
}
2026-04-07 15:12:09 +08:00
onMounted(() => {
if (route.params.data) {
const data = JSON.parse(decodeURIComponent(route.params.data));
console.log('@@@@data', data);
// todo 在有传参的时候 调用接口去获取数据 并且初始化表单
2026-04-15 11:48:35 +08:00
getDetail(data);
2026-04-07 15:12:09 +08:00
} else {
2026-04-09 11:35:50 +08:00
// console.log('无传入数据');
2026-04-07 15:12:09 +08:00
}
})
const handleClickBack = () => {
if (route.params.data) {
2026-04-15 11:48:35 +08:00
router.push('/')
2026-04-07 15:12:09 +08:00
} else {
router.push('/rebuild')
}
}
2026-04-07 16:29:39 +08:00
// 文件删除
const handleDelete = (file) => {
if (file.serverUrl) {
2026-04-09 11:35:50 +08:00
const index = form.fileList.findIndex((p) => p.fileUrl === file.serverUrl);
2026-04-07 16:29:39 +08:00
if (index !== -1) {
2026-04-09 11:35:50 +08:00
form.fileList.splice(index, 1);
2026-04-07 16:29:39 +08:00
}
}
};
// 文件上传
const afterRead = async (file) => {
2026-04-09 11:35:50 +08:00
const toast = showLoadingToast({
message: "上传中...",
forbidClick: true,
duration: 0, // 设置为0表示不会自动关闭
});
2026-04-07 16:29:39 +08:00
try {
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") {
2026-04-09 11:35:50 +08:00
// 根据文件类型设置fileType: 1-图片 2-视频
console.log('file', file)
let fileTypeValue = 1; // 默认图片
if (file.file.type.startsWith('video/')) {
fileTypeValue = 2; // 视频
}
form.fileList.push({
fileUrl: res.data,
fileType: fileTypeValue,
fileName: file.file.name,
});
2026-04-07 16:29:39 +08:00
const index = fileList.value.findIndex((f) => f.file === file.file);
if (index !== -1) {
fileList.value[index].serverUrl = res.data;
}
2026-04-09 11:35:50 +08:00
// console.log("form.fileList", toRaw(form.fileList));
// console.log("fileList.value", fileList.value);
2026-04-07 16:29:39 +08:00
} else {
throw new Error(res.message);
}
} catch (error) {
toast.close();
showToast({
type: "fail",
message: error.message,
});
}
};
2026-04-09 11:35:50 +08:00
const handleAdd = async () => {
// 先进行表单校验
if (!formRef.value) {
showToast('表单初始化失败');
return;
}
try {
const isValid = await formRef.value.validate();
// 表单校验通过,继续处理提交逻辑
const toast = showLoadingToast({
message: "上报中...",
forbidClick: true,
duration: 0, // 设置为0表示不会自动关闭
});
console.log('表单校验通过,提交数据:', form);
const res = await request({
url: '/snow-ops-platform/recovery/add',
method: 'POST',
data: form
})
toast.close();
if (res.code === '00000') {
2026-04-09 11:35:50 +08:00
showToast('提交成功');
handleClickBack();
} else {
2026-04-09 11:35:50 +08:00
showToast('提交失败, 请稍后重试或联系管理员');
}
} catch (error) {
// console.log('表单校验失败:', error);
showToast('请检查并完善表单信息');
}
}
const handleRouteNoChange = (item) => {
form.project.startStakeNo = item.startStakeNo
form.project.endStakeNo = item.endStakeNo
}
2026-04-09 11:35:50 +08:00
2026-04-07 15:12:09 +08:00
</script>
<style scoped lang="scss">
.content {
2026-04-07 16:29:39 +08:00
padding: 20px 0px 80px 0px;
2026-04-07 15:12:09 +08:00
}
.add-btn {
2026-04-07 16:29:39 +08:00
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;
2026-04-07 15:12:09 +08:00
}
</style>