275 lines
8.1 KiB
Vue
275 lines
8.1 KiB
Vue
<template>
|
|
<div class="page-container">
|
|
<el-card>
|
|
<template #header>
|
|
<span>{{ isEdit ? '编辑报价' : '创建报价' }}</span>
|
|
</template>
|
|
|
|
<el-form
|
|
ref="formRef"
|
|
:model="form"
|
|
:rules="rules"
|
|
label-width="120px"
|
|
style="max-width: 700px"
|
|
>
|
|
<el-form-item label="选择车辆" prop="vehicle_id">
|
|
<el-select
|
|
v-model="form.vehicle_id"
|
|
placeholder="请选择车辆"
|
|
style="width: 100%"
|
|
@change="handleVehicleChange"
|
|
:disabled="isEdit"
|
|
>
|
|
<el-option
|
|
v-for="vehicle in vehicleList"
|
|
:key="vehicle.id"
|
|
:label="`${vehicle.license_plate} - ${vehicle.brand} ${vehicle.model}`"
|
|
:value="vehicle.id"
|
|
/>
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="上年出险次数" prop="accident_count">
|
|
<el-input-number
|
|
v-model="form.accident_count"
|
|
:min="0"
|
|
:max="10"
|
|
style="width: 200px"
|
|
@change="handleAccidentChange"
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-divider content-position="left">商业险选择</el-divider>
|
|
|
|
<el-form-item label="车损险">
|
|
<el-switch v-model="form.has_damage" active-text="投保" inactive-text="不投" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="第三者责任险">
|
|
<el-switch v-model="form.has_third_party" active-text="投保" inactive-text="不投" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="三者保额" v-if="form.has_third_party">
|
|
<el-radio-group v-model="form.third_party_amount">
|
|
<el-radio :value="500000">50万</el-radio>
|
|
<el-radio :value="1000000">100万</el-radio>
|
|
<el-radio :value="2000000">200万</el-radio>
|
|
</el-radio-group>
|
|
</el-form-item>
|
|
|
|
<el-form-item label="盗抢险">
|
|
<el-switch v-model="form.has_theft" active-text="投保" inactive-text="不投" />
|
|
</el-form-item>
|
|
|
|
<el-form-item label="有效期至" prop="valid_until">
|
|
<el-date-picker
|
|
v-model="form.valid_until"
|
|
type="date"
|
|
placeholder="请选择有效期"
|
|
value-format="YYYY-MM-DD"
|
|
style="width: 200px"
|
|
/>
|
|
</el-form-item>
|
|
|
|
<el-divider content-position="left">保费预览</el-divider>
|
|
|
|
<el-descriptions :column="2" border v-if="selectedVehicle">
|
|
<el-descriptions-item label="车辆">
|
|
{{ selectedVehicle.license_plate }} {{ selectedVehicle.brand }} {{ selectedVehicle.model }}
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="购置价">{{ selectedVehicle.purchase_price.toLocaleString() }} 元</el-descriptions-item>
|
|
<el-descriptions-item label="交强险">
|
|
<span class="premium">{{ compulsoryPremium.toFixed(2) }} 元</span>
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="NCD系数">
|
|
<span class="premium">{{ ncdRatio }}</span>
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="商业险">
|
|
<span class="premium">{{ commercialPremium.toFixed(2) }} 元</span>
|
|
</el-descriptions-item>
|
|
<el-descriptions-item label="总保费">
|
|
<span class="total">{{ totalPremium.toFixed(2) }} 元</span>
|
|
</el-descriptions-item>
|
|
</el-descriptions>
|
|
|
|
<el-form-item style="margin-top: 20px">
|
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
|
{{ isEdit ? '保存修改' : '创建报价' }}
|
|
</el-button>
|
|
<el-button @click="handleBack">返回</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, computed, onMounted } from 'vue'
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import { ElMessage } from 'element-plus'
|
|
import type { FormInstance, FormRules } from 'element-plus'
|
|
import { getQuote, createQuote, updateQuote } from '../../api/quote'
|
|
import { getVehicles } from '../../api/vehicle'
|
|
import type { Vehicle } from '../../types'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const formRef = ref<FormInstance>()
|
|
|
|
const isEdit = computed(() => !!route.params.id)
|
|
|
|
const form = reactive({
|
|
vehicle_id: undefined as number | undefined,
|
|
accident_count: 0,
|
|
has_damage: true,
|
|
has_third_party: true,
|
|
third_party_amount: 1000000,
|
|
has_theft: true,
|
|
valid_until: '',
|
|
})
|
|
|
|
const rules: FormRules = {
|
|
vehicle_id: [{ required: true, message: '请选择车辆', trigger: 'change' }],
|
|
}
|
|
|
|
const submitting = ref(false)
|
|
const vehicleList = ref<Vehicle[]>([])
|
|
const selectedVehicle = ref<Vehicle | null>(null)
|
|
|
|
// 保费计算(与后端一致)
|
|
function getNcdRatio(accidentCount: number): number {
|
|
if (accidentCount === 0) return 0.7
|
|
if (accidentCount === 1) return 0.8
|
|
if (accidentCount === 2) return 1.0
|
|
if (accidentCount === 3) return 1.1
|
|
return 1.2
|
|
}
|
|
|
|
function getCompulsoryPremium(seatCount: number): number {
|
|
return seatCount <= 6 ? 950 : 1100
|
|
}
|
|
|
|
const ncdRatio = computed(() => getNcdRatio(form.accident_count))
|
|
|
|
const compulsoryPremium = computed(() => {
|
|
if (!selectedVehicle.value) return 0
|
|
return getCompulsoryPremium(selectedVehicle.value.seat_count)
|
|
})
|
|
|
|
const commercialPremium = computed(() => {
|
|
if (!selectedVehicle.value) return 0
|
|
const price = selectedVehicle.value.purchase_price
|
|
let total = 0
|
|
if (form.has_damage) {
|
|
total += price * 0.015
|
|
}
|
|
if (form.has_third_party) {
|
|
const amount = form.third_party_amount
|
|
if (amount === 500000) total += 800
|
|
else if (amount === 1000000) total += 1200
|
|
else if (amount === 2000000) total += 1800
|
|
}
|
|
if (form.has_theft) {
|
|
total += price * 0.005
|
|
}
|
|
return total
|
|
})
|
|
|
|
const totalPremium = computed(() => {
|
|
return (compulsoryPremium.value + commercialPremium.value) * ncdRatio.value
|
|
})
|
|
|
|
async function loadVehicles() {
|
|
try {
|
|
const res = await getVehicles({ page: 1, pageSize: 100 })
|
|
vehicleList.value = res.data.list
|
|
} catch (e: any) {
|
|
ElMessage.error(e.message || '获取车辆列表失败')
|
|
}
|
|
}
|
|
|
|
function handleVehicleChange(vehicleId: number) {
|
|
selectedVehicle.value = vehicleList.value.find(v => v.id === vehicleId) || null
|
|
}
|
|
|
|
function handleAccidentChange(value: number) {
|
|
form.accident_count = value
|
|
}
|
|
|
|
async function loadDetail() {
|
|
const id = Number(route.params.id)
|
|
try {
|
|
const res = await getQuote(id)
|
|
Object.assign(form, {
|
|
vehicle_id: res.data.vehicle_id,
|
|
accident_count: res.data.accident_count,
|
|
has_damage: res.data.commercial_premium > 0,
|
|
has_third_party: true,
|
|
third_party_amount: 1000000,
|
|
has_theft: res.data.commercial_premium > 0,
|
|
valid_until: res.data.valid_until,
|
|
})
|
|
const vehicle = vehicleList.value.find(v => v.id === res.data.vehicle_id)
|
|
if (vehicle) {
|
|
selectedVehicle.value = vehicle
|
|
}
|
|
} catch (e: any) {
|
|
ElMessage.error(e.message || '获取报价信息失败')
|
|
}
|
|
}
|
|
|
|
async function handleSubmit() {
|
|
if (!formRef.value) return
|
|
const valid = await formRef.value.validate().catch(() => false)
|
|
if (!valid) return
|
|
|
|
submitting.value = true
|
|
try {
|
|
const data = {
|
|
vehicle_id: form.vehicle_id,
|
|
accident_count: form.accident_count,
|
|
has_damage: form.has_damage,
|
|
has_third_party: form.has_third_party,
|
|
third_party_amount: form.third_party_amount,
|
|
has_theft: form.has_theft,
|
|
valid_until: form.valid_until,
|
|
}
|
|
if (isEdit.value) {
|
|
await updateQuote(Number(route.params.id), data)
|
|
ElMessage.success('保存成功')
|
|
} else {
|
|
await createQuote(data)
|
|
ElMessage.success('报价创建成功')
|
|
}
|
|
router.push('/quotes')
|
|
} catch (e: any) {
|
|
ElMessage.error(e.message || '操作失败')
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
|
|
function handleBack() {
|
|
router.push('/quotes')
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await loadVehicles()
|
|
if (isEdit.value) {
|
|
await loadDetail()
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.premium {
|
|
font-weight: 600;
|
|
color: #409eff;
|
|
}
|
|
|
|
.total {
|
|
font-weight: 700;
|
|
color: #e6a23c;
|
|
font-size: 18px;
|
|
}
|
|
</style> |