| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- <template>
- <el-dialog title="整单退保" width="1000" v-model="isDialogVisible" @close="handleClose">
- <div class="">
- <div class="mb-4">
- <div class="text-[#333333] text-base font-medium">车辆{{ props.data.licenseNo }}整单退保</div>
- <div class="text-[#666666]">退保后,将重新计算该保单的应收,应付金额。</div>
- </div>
- <el-table :data="policyItems" border stripe
- header-cell-class-name="!bg-gray-100 !text-gray-600"
- @selection-change="handleSelectionChange">
- <el-table-column type="selection" width="55" align="center" />
- <el-table-column prop="kindName" label="保险" />
- <el-table-column prop="policyNumber" label="保单号" width="220" />
- <el-table-column prop="expiryDate" label="终保日期" width="180" />
- <el-table-column prop="premium" label="保费" width="120">
- <template #default="{ row }">
- ¥ {{ row.premium }}
- </template>
- </el-table-column>
- <el-table-column label="退款金额" width="250">
- <template #default="{ row, $index }">
- <el-input v-model="row.refundAmount"
- type="number"
- placeholder="选中后可输入"
- :disabled="!isRowSelected(row)"
- :style="[
- row.errors?.refundAmount ? {
- '--el-border-color': '#F56C6C',
- '--el-border-color-hover': '#F56C6C',
- '--el-color-primary': '#F56C6C'
- } : {}
- ]"
- @blur="currentIndex = undefined"
- @focus="currentIndex = $index"
- @input="validateInput(row)"
- />
- <!-- 错误提示 -->
- <div v-if="row.errors?.refundAmount && currentIndex === $index" class="error-message">
- {{ row.errors.refundAmount }}
- </div>
- </template>
- </el-table-column>
- </el-table>
- </div>
- <template #footer>
- <div class="px-1">
- <el-button class="border-[#0083FF] color-[#0083FF]" plain @click="isDialogVisible = false">取 消</el-button>
- <el-button type="primary" @click="handleSubmit">提交退保申请</el-button>
- </div>
- </template>
- </el-dialog>
- </template>
- <script setup lang="ts">
- import api from '@/api';
- import { ElMessage } from 'element-plus';
- // 组件属性与事件
- const props = defineProps({
- data: {
- type: Object,
- default: {}
- }
- });
- const isDialogVisible = defineModel({
- default: false
- });
- const emits = defineEmits(['complete']);
- const isSubmit = ref(false);
- watch(isDialogVisible, (newVal) => {
- if (newVal) isSubmit.value = false;
- });
- // 表格的原始数据
- const policyItems = ref<any>([]);
- watch(() => props.data.tableList, (val) => {
- policyItems.value = val;
- }, {
- immediate: false,
- });
- // 当前操作行的索引
- const currentIndex = ref();
- // 存储当前所有被选中的行的数据
- interface TableRow {
- [key: string]: any
- }
- const selectedRows = ref<TableRow[]>([]);
- // 关闭弹窗
- const handleClose = () => {
- isDialogVisible.value = false;
- clearData();
- if (!isSubmit.value) {
- api.insurancePolicyApi.adjustRemove(props.data.orderNo);
- }
- };
- // 清空数据,以防残留数据
- const clearData = () => {
- policyItems.value = [];
- };
- // selection参数是所有被选中行的数据组成的数组
- const handleSelectionChange = (selection: any) => {
- selectedRows.value = selection;
- // 当某一行被取消选中时,清空其退款金额
- policyItems.value.forEach((item: any) => {
- if (!selection.some((selected: any) => selected.id === item.id)) {
- item.refundAmount = null;
- }
- });
- };
- // 辅助函数:判断某一行是否被选中
- const isRowSelected = (row: any): boolean => {
- return selectedRows.value.some((item: any) => item.id === row.id);
- };
- // 校验规则
- const validateRules = {
- refundAmount: (value: any, compare: any) => {
- if (value > compare) {
- return '退款金额不能大于保费';
- }
- if (value < 0 || value > 99999.99) {
- return '请输入0-99999.99之间的数字';
- } else {
- // 检查小数位数是否超过2位
- const decimalPart = value.toString().split('.')[1];
- if (decimalPart && decimalPart.length > 2) {
- return '最多支持两位小数';
- }
- }
- return ''; // 校验通过
- }
- }
- // 输入时实时校验格式
- const validateInput = (row: any) => {
- if (row.refundAmount === null || row.refundAmount === '') return;
- const field = 'refundAmount';
- const errorMsg = validateRules[field](row[field], row.premium);
- row.errors = {
- [field]: errorMsg
- };
- // // 清除非数字和非小数点的字符,但保留第一个小数点
- // let value = row.refundAmount.replace(/[^\d.]/g, '');
- // const parts = value.split('.');
- // if (parts.length > 2) {
- // value = parts[0] + '.' + parts.slice(1).join('');
- // }
- // // 限制小数位数
- // if (parts[1] && parts[1].length > 2) {
- // parts[1] = parts[1].substring(0, 2);
- // value = parts.join('.');
- // }
- // // 限制整数位数
- // if (parts[0].length > 5) {
- // parts[0] = parts[0].substring(0, 5);
- // value = parts.join('.');
- // }
- // row.refundAmount = value;
- };
- // 提交退保申请
- const handleSubmit = () => {
- // 检查是否至少选择了一项
- if (selectedRows.value.length === 0) {
- ElMessage.warning('请至少选择一个需要退保的险种。');
- return;
- }
- // 遍历所有选中的行进行校验
- for (const row of selectedRows.value) {
- const refundAmountStr = row.refundAmount;
- // 1. 校验是否为空
- if (refundAmountStr === null || refundAmountStr.trim() === '') {
- ElMessage.error(`保险“${row.kindName}”:请输入退款金额`);
- return; // 中断提交
- }
- // 2. 校验格式:必须是数字,最多5位整数,2位小数
- const regex = /^\d{1,5}(\.\d{1,2})?$/;
- if (!regex.test(refundAmountStr)) {
- ElMessage.error(`保险“${row.kindName}”:请输入0-99999.99之间的数字(仅支持2位小数)`);
- return; // 中断提交
- }
- const refundAmountNum = parseFloat(refundAmountStr);
- // 3. 校验退款金额是否大于保费
- if (refundAmountNum > row.premium) {
- ElMessage.error(`保险“${row.kindName}”:退款金额不能大于保费(¥ ${row.premium})`);
- return; // 中断提交
- }
- }
- // 提交数据
- let params = {
- id: props.data.adjustId,
- orderNo: props.data.orderNo,
- infoVosList: selectedRows.value.map((item: any) => {
- let { errors, ...datas } = item;
- return {
- ...datas,
- // 退款金额
- refundAmount: item.refundAmount - 0,
- }
- })
- };
- console.log('params:', params);
- console.log('校验通过,准备提交的数据:', selectedRows.value);
- api.insurancePolicyApi.refundSubmit(params).then((res: any) => {
- if (res.code === 200) {
- ElMessage.success(res.msg || '退保申请已提交!');
- // 关闭弹窗
- isSubmit.value = true;
- isDialogVisible.value = false;
- // emits
- emits('complete');
- }
- });
- };
- onUnmounted(() => {
- if (isDialogVisible.value) {
- console.log('处理页面刷新时,单子没关闭')
- clearData();
- api.insurancePolicyApi.adjustRemove(props.data.orderNo);
- }
- });
- </script>
- <style scoped lang="scss">
- .error-message {
- width: fit-content;
- font-size: 12px;
- color: #fff;
- padding: 3px 6px;
- text-align: justify;
- line-height: 14px;
- border-radius: 2px;
- position: absolute;
- background: #F56C6C;
- left: 12px;
- right: 12px;
- bottom: calc(100% - 8px);
- }
- </style>
|