Compare commits

...

2 Commits

4 changed files with 239 additions and 90 deletions

View File

@ -37,7 +37,7 @@ import { showToast, showSuccessToast, showFailToast } from 'vant'
import PageContainer from '@/components/PageContainer.vue'
import CurrentSite from '@/components/CurrentSite.vue'
import PanelItem from '@/components/PanelItem.vue'
import WaterDisaster from './WaterDisaster.vue'
import WaterDisaster from './WaterDisaster/WaterDisaster.vue'
const router = useRouter()

View File

@ -0,0 +1,159 @@
<template>
<!-- 损失计算弹窗 -->
<van-dialog
v-model:show="visible"
title="塌方损失信息"
show-cancel-button
@confirm="confirm"
@cancel="cancelLoss"
confirm-button-text="确定"
cancel-button-text="取消"
>
<div class="loss-dialog-content">
<!-- 塌方长 -->
<van-field v-model="formData.length" label="塌方长" placeholder="请填写长度" type="digit" clearable>
<template #button>
<span class="field-unit"></span>
</template>
</van-field>
<!-- 塌方宽 -->
<van-field v-model="formData.width" label="塌方宽" placeholder="请填写宽度" type="digit" clearable>
<template #button>
<span class="field-unit"></span>
</template>
</van-field>
<!-- 塌方高 -->
<van-field v-model="formData.height" label="塌方高" placeholder="请填写高度" type="digit" clearable>
<template #button>
<span class="field-unit"></span>
</template>
</van-field>
<!-- 单价 (0-2000) -->
<van-field v-model="formData.unitPrice" label="单价(0-2000元)" placeholder="请填写单价" type="digit" clearable>
<template #button>
<span class="field-unit"></span>
</template>
</van-field>
<van-field v-model="formData.totalPrice" label="塌方损失金额" placeholder="请填写金额" type="digit" clearable>
<template #button>
<span class="field-unit"></span>
</template>
</van-field>
</div>
</van-dialog>
</template>
<script setup>
import { onMounted, ref, reactive, watch, computed } from 'vue'
import { showToast } from 'vant'
//
const visible = ref(false)
//
const formData = ref({
length: '',
width: '',
height: '',
unitPrice: ''
})
const totalPrice = computed(() => {
const l = parseFloat(formData.value.length)
const w = parseFloat(formData.value.width)
const h = parseFloat(formData.value.height)
const price = parseFloat(formData.value.unitPrice)
if (isNaN(l) || l <= 0) {
return 0
}
if (isNaN(w) || w <= 0) {
return 0
}
if (isNaN(h) || h <= 0) {
return 0
}
if (isNaN(price) || price < 0) {
return 0
}
if (price > 2000) {
return 0
}
return (l * w * h * price)
})
watch(totalPrice, ()=>{
formData.value.totalPrice = totalPrice.value
})
//
const show = () => {
visible.value = true
}
//
const validateForm = () => {
const l = parseFloat(formData.length)
const w = parseFloat(formData.width)
const h = parseFloat(formData.height)
const price = parseFloat(formData.unitPrice)
if (isNaN(l) || l <= 0) {
showToast('请填写有效的塌方长度')
return false
}
if (isNaN(w) || w <= 0) {
showToast('请填写有效的塌方宽度')
return false
}
if (isNaN(h) || h <= 0) {
showToast('请填写有效的塌方高度')
return false
}
if (isNaN(price) || price < 0) {
showToast('请填写有效的单价')
return false
}
if (price > 2000) {
showToast('单价不能超过2000元')
return false
}
return true
}
//
const confirm = () => {
if(!formData.value.totalPrice) {
showToast('请填写损失金额')
return
}
emit('confirm', formData.value.totalPrice)
//
resetForm()
visible.value = false
}
//
const cancelLoss = () => {
resetForm()
visible.value = false
}
//
const resetForm = () => {
formData.value.length = ''
formData.value.width = ''
formData.value.height = ''
formData.value.unitPrice = ''
formData.value.totalPrice
}
//
const emit = defineEmits(['confirm'])
defineExpose({
show
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,72 @@
<template>
<div class="loss-list">
<template v-for="item in modelValue">
<van-field v-model="item.value" label="塌方及损失" placeholder="请填写" type="digit" @click="cubeCalculateDialog.show()">
<template #button>
<span class="field-unit">/万元</span>
</template>
</van-field>
</template>
<CubeCalculateDialog ref="cubeCalculateDialog" />
</div>
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import CubeCalculateDialog from './CubeCalculateDialog.vue';
const props = defineProps({
modelValue: {
type: Object,
default: () => ({})
}
})
const cubeCalculateDialog = ref(null)
</script>
<style scoped lang="scss">
.field-unit {
color: #969799;
font-size: 14px;
margin-left: 4px;
}
.loss-dialog-content {
padding: 16px;
:deep(.van-field) {
margin-bottom: 12px;
}
}
.calculation-preview {
background-color: #f7f8fa;
border-radius: 8px;
padding: 12px;
margin-top: 12px;
.preview-item {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
&:last-child {
margin-bottom: 0;
}
.preview-label {
color: #646566;
font-size: 14px;
}
.preview-value {
color: #ee0a24;
font-size: 14px;
font-weight: 500;
}
}
}
</style>

View File

@ -120,11 +120,8 @@
<!-- 灾毁损失 -->
<PanelItem title="灾毁损失">
<div class="loss-row">
<span class="loss-label">塌方及损失</span>
<span class="loss-value">{{ formData.collapseLoss }}/万元</span>
</div>
<van-button size="small" block type="primary" plain @click="showLossDialog = true">添加损失</van-button>
<LossList v-model="formData.lossList" />
<van-button size="small" block type="primary" plain>添加损失</van-button>
<van-field v-model="formData.handlingSituation" label="处理情况" placeholder="请填写(选填)" />
<van-field v-model="formData.totalLossAmount" label="损失总金额" placeholder="请填写(选填)" type="digit">
<template #button>
@ -152,8 +149,7 @@
<van-field v-model="formData.siteDescription" label="现场描述" placeholder="请填写" type="textarea" rows="2" autosize />
<van-field label="附件">
<template #input>
</template>
<template #input> </template>
</van-field>
</PanelItem>
@ -186,18 +182,6 @@
<video :src="formData.videoFile[0].content" controls style="width: 100%; max-height: 200px"></video>
</div>
</PanelItem> -->
<!-- 损失计算弹窗 -->
<van-dialog v-model:show="showLossDialog" title="添加塌方损失" show-cancel-button @confirm="confirmLoss" @cancel="showLossDialog = false">
<div class="loss-dialog-content">
<van-field v-model="lossForm.length" label="长度(m)" type="number" placeholder="请输入长度" />
<van-field v-model="lossForm.width" label="宽度(m)" type="number" placeholder="请输入宽度" />
<van-field v-model="lossForm.height" label="高度(m)" type="number" placeholder="请输入高度" />
<van-field v-model="lossForm.unitPrice" label="单价(元/m³)" type="number" placeholder="请输入单价" />
<div class="loss-calc-result">预估塌方量{{ calculatedVolume }} </div>
<div class="loss-calc-result">预估损失{{ calculatedLoss }} 万元</div>
</div>
</van-dialog>
</div>
</template>
@ -207,6 +191,7 @@ import { showToast, showFailToast } from 'vant'
import PanelItem from '@/components/PanelItem.vue'
import BasePicker from '@/components/BasePicker.vue'
import BaseDatePicker from '@/components/BaseDatePicker.vue'
import LossList from './LossList.vue'
// props
const props = defineProps({
@ -244,7 +229,7 @@ const formData = reactive({
strandedPeople: '',
damagedVehicles: '',
strandedVehicles: '',
collapseLoss: '0',
collapseLoss: [],
handlingSituation: '',
totalLossAmount: '',
machineryInput: '',
@ -252,12 +237,10 @@ const formData = reactive({
fundsInput: '',
siteDescription: '',
imageFiles: [],
videoFile: []
videoFile: [],
lossList: [{ value: '' }]
})
//
const showLossDialog = ref(false)
// BasePicker
const roadConditionOptions = [
{ label: '高速公路', value: '高速公路' },
@ -284,30 +267,6 @@ const repairProgressOptions = [
const minDate = new Date(2020, 0, 1)
const maxDate = new Date(2030, 11, 31)
//
const lossForm = reactive({
length: '',
width: '',
height: '',
unitPrice: ''
})
//
const calculatedVolume = computed(() => {
const l = parseFloat(lossForm.length) || 0
const w = parseFloat(lossForm.width) || 0
const h = parseFloat(lossForm.height) || 0
return (l * w * h).toFixed(2)
})
//
const calculatedLoss = computed(() => {
const volume = parseFloat(calculatedVolume.value) || 0
const price = parseFloat(lossForm.unitPrice) || 0
const lossYuan = volume * price
return (lossYuan / 10000).toFixed(2)
})
//
watch(
() => props.modelValue,
@ -350,27 +309,6 @@ const calibrateEndCoord = () => {
showToast('止点经纬度已校准')
}
//
const confirmLoss = () => {
const lossValue = calculatedLoss.value
if (parseFloat(lossValue) > 0) {
formData.collapseLoss = lossValue
if (formData.totalLossAmount) {
const currentTotal = parseFloat(formData.totalLossAmount) || 0
formData.totalLossAmount = (currentTotal + parseFloat(lossValue)).toFixed(2)
} else {
formData.totalLossAmount = lossValue
}
} else {
showToast('请填写有效的长宽高和单价')
}
lossForm.length = ''
lossForm.width = ''
lossForm.height = ''
lossForm.unitPrice = ''
showLossDialog.value = false
}
//
const afterImageRead = (file) => {
console.log('图片上传:', file)
@ -415,7 +353,6 @@ defineExpose({
<style lang="scss" scoped>
.water-disaster {
.coordinate-row {
display: flex;
gap: 8px;
@ -465,25 +402,6 @@ defineExpose({
}
}
.loss-row {
display: flex;
align-items: center;
justify-content: space-between;
background: #f8f9fa;
padding: 10px 12px;
border-radius: 8px;
margin: 12px 0;
.loss-label {
font-size: 14px;
color: #323233;
}
.loss-value {
font-size: 16px;
font-weight: 600;
color: #ee0a24;
}
}
.attachment-tip {
font-size: 12px;
color: #969799;