<template>
|
<el-dialog v-model="visible" :title="type === 'receivable' ? '应收账单结算' : '应付账单结算'" width="1200px" destroy-on-close
|
@closed="handleClosed">
|
<el-descriptions title="账单信息" :column="3" border class="mb-5">
|
<el-descriptions-item label="系统编号">{{ billInfo.systemNo }}</el-descriptions-item>
|
<el-descriptions-item label="账单名称">{{ billInfo.billName }}</el-descriptions-item>
|
<el-descriptions-item v-if="type == 'receivable'" label="客户名称">{{ billInfo.customerName
|
}}</el-descriptions-item>
|
<el-descriptions-item v-if="type == 'payable'" label="供应商名称">{{ billInfo.supplierName
|
}}</el-descriptions-item>
|
|
<el-descriptions-item label="单据数量">{{ billInfo.documentCount }}</el-descriptions-item>
|
<el-descriptions-item label="应结算金额">
|
<span class="text-bold">{{ billInfo.totalAmount }}</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="币制">{{ billInfo.currency }}</el-descriptions-item>
|
|
<el-descriptions-item label="减免金额">{{ billInfo.discountAmount }}</el-descriptions-item>
|
<el-descriptions-item v-if="type == 'receivable'" label="已收金额">{{ billInfo.receivedAmount
|
}}</el-descriptions-item>
|
<el-descriptions-item v-if="type == 'payable'" label="已付金额">{{ billInfo.receivedAmount
|
}}</el-descriptions-item>
|
|
<el-descriptions-item v-if="type == 'receivable'" label="待收金额">
|
<span class="text-danger">{{ billInfo.pendingAmount }}</span>
|
</el-descriptions-item>
|
|
<el-descriptions-item v-if="type == 'payable'" label="待付金额">
|
<span class="text-danger">{{ billInfo.pendingAmount }}</span>
|
</el-descriptions-item>
|
|
<el-descriptions-item label="周期类型">
|
{{ billInfo.periodType }}
|
</el-descriptions-item>
|
<el-descriptions-item label="业务期间">
|
<span v-if="billInfo.businessEndDate !== null">{{ billInfo.businessEndDate + '-' }}</span>
|
<span v-if="billInfo.businessStartDate !== null">
|
{{ billInfo.businessStartDate }}
|
</span>
|
</el-descriptions-item>
|
<el-descriptions-item label="账单周期">
|
<span v-if="billInfo.billingStartDate !== null">{{ billInfo.billingStartDate + '-' }}</span>
|
<span v-if="billInfo.billingEndDate !== null">
|
{{ billInfo.billingEndDate }}
|
</span>
|
</el-descriptions-item>
|
|
<el-descriptions-item label="账单生成日期">{{ billInfo.billGenerateDate }}</el-descriptions-item>
|
<el-descriptions-item label="账单发送日期">{{ billInfo.billSendDate }}</el-descriptions-item>
|
<el-descriptions-item label="账单到期日期">{{ billInfo.billDueDate }}</el-descriptions-item>
|
</el-descriptions>
|
|
<h3 class="section-title">本次结算信息</h3>
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="110px" label-position="right">
|
<el-row :gutter="20">
|
<el-col :span="8">
|
<el-form-item label="结算方式" prop="settlementMethod">
|
<el-select v-model="formData.settlementMethod" placeholder="请选结算方式" clearable>
|
<el-option v-for="dict in sys_clearing_form" :key="dict.value" :label="dict.label"
|
:value="dict.value" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="客户银行账户" prop="customerBankAccount">
|
<el-input v-model="formData.customerBankAccount" @click="openBankDialog('customer')" readonly
|
placeholder="点击选择">
|
<template #append>
|
<el-button icon="Search" @click="openBankDialog('customer')" />
|
</template>
|
</el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="付款银行账户" prop="paymentBankAccount">
|
<el-input v-model="formData.paymentBankAccount" @click="openBankDialog('receiving')"
|
placeholder="点击选择">
|
<template #append>
|
<el-button icon="Search" @click="openBankDialog('receiving')" />
|
</template>
|
</el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="客户开户行">
|
<el-input v-model="formData.customerBank" disabled />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="付款账户开户行">
|
<el-input v-model="formData.paymentBank" disabled />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="收款银行账户" prop="receivingBankAccount">
|
<el-input v-model="formData.receivingBankAccount" @click="openBankDialog('receiving')" readonly
|
placeholder="请输入收款银行账户">
|
<template #append>
|
<el-button icon="Search" @click="openBankDialog('receiving')" />
|
</template>
|
</el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="收款账户开户行">
|
<el-input v-model="formData.receivingBank" disabled />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="收款银行账户" prop="supplierReceivingAccount">
|
<el-input v-model="formData.supplierReceivingAccount" @click="openBankIsibleDialog" readonly
|
placeholder="请输入收款银行账户">
|
<template #append>
|
<el-button icon="Search" @click="openBankIsibleDialog" />
|
</template>
|
</el-input>
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="收款账户开户行">
|
<el-input v-model="formData.supplierReceivingBank" disabled />
|
</el-form-item>
|
</el-col>
|
<!-- 少 -->
|
<el-col :span="8">
|
<el-form-item label="收款人">
|
<el-input v-model="formData.payee" />
|
</el-form-item>
|
</el-col>
|
|
</el-row>
|
|
<el-row :gutter="20">
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="收款日期" prop="receiptDate">
|
<el-date-picker v-model="formData.receiptDate" type="date" placeholder="请选择日期"
|
style="width: 100%" value-format="YYYY-MM-DD" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="付款日期" prop="paymentDate">
|
<el-date-picker v-model="formData.paymentDate" type="date" placeholder="请选择日期"
|
style="width: 100%" value-format="YYYY-MM-DD" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="收款金额" prop="receiptAmount">
|
<el-input-number v-model="formData.receiptAmount" :precision="2" :min="0" style="width: 100%"
|
@change="calcRemaining" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="付款金额" prop="paymentAmount">
|
<el-input-number v-model="formData.paymentAmount" :precision="2" :step="0.1" :min="0"
|
style="width: 100%" @change="calcRemainingA" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'receivable'">
|
<el-form-item label="收款后待收金额">
|
<el-input v-model="formData.remainingPendingAmount" disabled class="remaining-input" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="8" v-if="type == 'payable'">
|
<el-form-item label="收款后待付金额">
|
<el-input v-model="formData.remainingPendingAmount" disabled class="remaining-input" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
|
<template #footer>
|
<el-button @click="openIshpw">取消</el-button>
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">确定</el-button>
|
</template>
|
</el-dialog>
|
|
<bankCardData v-model:visible="bankDialogVisible"
|
:default-selected-id="currentSelectType === 'customer' ? formData.bankAccountId : formData.receivingBankAccountId"
|
:mode="currentSelectType === 'customer' ? 'config' : 'internal'" @confirm="handleBankConfirm" />
|
|
<supplierBankCardData v-model:visible="supplierBankIsible" :default-selected-id="formData.supplierId"
|
@confirm="handleBankCardfirm" />
|
</template>
|
|
<script setup lang="ts">
|
import { ref, reactive, nextTick } from 'vue'
|
import { ElMessage } from 'element-plus'
|
import useCurrentInstance from "@/utils/useCurrentInstance";
|
import bankCardData from "../bankCardData/index.vue";
|
import supplierBankCardData from "../supplierBankCardData/index.vue";
|
|
|
const props = defineProps<{
|
type: 'receivable' | 'payable' // 类型:应收或应付
|
}>()
|
|
const { proxy } = useCurrentInstance();
|
// 获取所需字典数据
|
const {
|
sys_clearing_form
|
} = proxy.useDict(
|
'sys_clearing_form'
|
);
|
const emit = defineEmits(['success'])
|
|
const visible = ref(false)
|
const submitting = ref(false)
|
const formRef = ref()
|
|
// 账单详情数据
|
const billInfo = ref<any>({})
|
|
// 表单数据
|
// 修改后的表单数据
|
const formData = reactive({
|
settlementMethod: '',
|
customerBankAccount: '',
|
customerBank: '',
|
paymentBankAccount: '', // 新增
|
paymentBank: '', // 新增
|
receivingBankAccount: '',
|
receivingBank: '',
|
receivingBankAccountId: '',
|
operator: '',
|
bankAccountId: '',
|
|
// 建议:如果你想逻辑更清晰,可以把 receiptAmount 和 paymentAmount 统一或在计算时做判断
|
receiptAmount: 0,
|
paymentAmount: 0,
|
remainingPendingAmount: 0,
|
|
receiptDate: '',
|
paymentDate: '', // 新增
|
})
|
|
// 校验规则
|
const rules = {
|
// 结算方式
|
settlementMethod: [{ required: true, message: '请选择结算方式', trigger: 'change' }],
|
|
// 收款相关校验 (type === 'receivable')
|
receiptDate: [{ required: true, message: '请选择收款日期', trigger: 'change' }],
|
receiptAmount: [
|
{ required: true, message: '请输入收款金额', trigger: 'blur' },
|
{ type: 'number', min: 0.01, message: '金额必须大于0', trigger: 'blur' }
|
],
|
|
// 付款相关校验 (type === 'payable' - 如果你后续取消注释的话)
|
settleDate: [{ required: true, message: '请选择付款日期', trigger: 'change' }],
|
settleAmount: [
|
{ required: true, message: '请输入付款金额', trigger: 'blur' },
|
{ type: 'number', min: 0.01, message: '金额必须大于0', trigger: 'blur' }
|
]
|
}
|
// 打开弹窗
|
const open = (row: any) => {
|
visible.value = true
|
billInfo.value = { ...row }
|
|
// 初始化本次收款金额:默认填入全部待收金额(用户可改)
|
formData.receiptAmount = row.pendingAmount || 0;
|
formData.paymentAmount = row.pendingAmount || 0
|
calcRemaining()
|
}
|
// 计算剩余待收/待付
|
const calcRemaining = () => {
|
// 1. 获取原始待收金额 (从 billInfo 中获取)
|
const pending = Number(billInfo.value.pendingAmount || 0);
|
|
// 2. 获取当前输入的收款金额 (注意:你 HTML 中绑定的是 receiptAmount)
|
const current = Number(formData.receiptAmount || 0);
|
|
// 3. 计算差值并保留 2 位小数
|
// 使用 Number().toFixed(2) 确保精度,再转回 Number 以便后续逻辑使用
|
formData.remainingPendingAmount = Number((pending - current).toFixed(2));
|
};
|
|
// 弹窗显示状态
|
const bankDialogVisible = ref(false);
|
|
// 定义一个标识,记录当前是谁在选银行
|
const currentSelectType = ref<'customer' | 'receiving'>('customer');
|
|
// 修改打开弹窗的方法,传入标识
|
const openBankDialog = (type: 'customer' | 'receiving') => {
|
currentSelectType.value = type;
|
bankDialogVisible.value = true;
|
};
|
const openIshpw = () => {
|
visible.value = false
|
}
|
|
|
// 处理确认回调
|
const handleBankConfirm = (data: any) => {
|
console.log(props.type);
|
console.log(currentSelectType.value);
|
|
|
if (currentSelectType.value === 'customer') {
|
// 填充客户银行信息
|
if (props.type === 'payable') {
|
formData.bankAccountId = data.id;
|
formData.paymentBankAccount = data.accountNo;
|
formData.paymentBank = data.bankName;
|
|
} else {
|
formData.bankAccountId = data.id;
|
formData.customerBankAccount = data.accountNo;
|
formData.customerBank = data.bankName;
|
}
|
|
} else {
|
// 填充收款银行信息 (对应你代码里的 receivingBankAccount 等)
|
if (props.type === 'payable') {
|
formData.bankAccountId = data.id;
|
formData.paymentBankAccount = data.accountNo;
|
formData.paymentBank = data.bankName;
|
} else {
|
formData.receivingBankAccountId = data.id; // 建议在 formData 增加此 ID 字段用于回显
|
formData.receivingBankAccount = data.accountNo;
|
formData.receivingBank = data.bankName;
|
}
|
|
}
|
};
|
|
// 提交
|
const handleSubmit = async () => {
|
await formRef.value.validate()
|
submitting.value = true
|
|
try {
|
// 模拟API调用
|
// console.log('提交数据:', { ...formData, billId: billInfo.value.id, type: props.type })
|
// await new Promise(resolve => setTimeout(resolve, 1000))
|
|
emit('success', formData)
|
// visible.value = false
|
} catch (error) {
|
console.error(error)
|
} finally {
|
submitting.value = false
|
}
|
}
|
|
// 4. 修改重置逻辑
|
const handleClosed = () => {
|
formRef.value?.resetFields()
|
Object.assign(formData, {
|
settlementMethod: '',
|
receiptDate: '',
|
receiptAmount: 0,
|
customerBankAccount: '',
|
customerBank: '',
|
receivingBankAccount: '',
|
receivingBank: '',
|
// ... 其他需要清空的字段
|
})
|
billInfo.value = {}
|
}
|
|
// 计算剩余待收/待付
|
const calcRemainingA = () => {
|
// 1. 获取原始待收/待付总额 (从账单信息读取)
|
const pending = Number(billInfo.value.pendingAmount || 0);
|
|
// 2. 根据类型获取当前输入的金额
|
// 如果是应收(receivable),取 receiptAmount;如果是应付(payable),取 paymentAmount
|
const currentInput = props.type === 'receivable'
|
? Number(formData.receiptAmount || 0)
|
: Number(formData.paymentAmount || 0);
|
|
// 3. 计算结果并保留两位小数
|
const result = pending - currentInput;
|
formData.remainingPendingAmount = Number(result.toFixed(2));
|
};
|
|
|
// 弹窗显示状态
|
const supplierBankIsible = ref(false);
|
|
|
// 修改打开弹窗的方法,传入标识
|
const openBankIsibleDialog = () => {
|
supplierBankIsible.value = true;
|
};
|
const handleBankCardfirm = (data: any) => {
|
formData.supplierId = data.id; // 建议在 formData 增加此 ID 字段用于回显
|
formData.supplierReceivingAccount = data.accountNo;
|
formData.supplierReceivingBank = data.bankName;
|
|
};
|
defineExpose({ open, openIshpw })
|
</script>
|
|
<style scoped>
|
.mb-5 {
|
margin-bottom: 20px;
|
}
|
|
.section-title {
|
font-size: 16px;
|
font-weight: bold;
|
margin: 20px 0;
|
padding-left: 10px;
|
border-left: 4px solid #409eff;
|
}
|
|
.text-bold {
|
font-weight: bold;
|
font-size: 15px;
|
}
|
|
.text-danger {
|
color: #f56c6c;
|
font-weight: bold;
|
}
|
|
.remaining-input :deep(.el-input__inner) {
|
color: #e6a23c;
|
font-weight: bold;
|
}
|
|
:deep(.el-descriptions__label) {
|
width: 120px;
|
background-color: #f5f7fa !important;
|
}
|
|
::v-deep .el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell {
|
border: var(--el-descriptions-table-border);
|
padding: 8px 11px;
|
width: 200px;
|
}
|
</style>
|