feat:【antd】【erp 系统】finance/payment 的迁移 2/4(form 部分)
This commit is contained in:
@@ -3,22 +3,53 @@ import type { PageParam, PageResult } from '@vben/request';
|
||||
import { requestClient } from '#/api/request';
|
||||
|
||||
namespace ErpFinancePaymentApi {
|
||||
/** 付款单项 */
|
||||
export interface FinancePaymentItem {
|
||||
id?: number;
|
||||
row_id?: number; // 前端使用的临时ID
|
||||
bizId: number; // 业务ID
|
||||
bizType: number; // 业务类型
|
||||
bizNo: string; // 业务编号
|
||||
totalPrice: number; // 应付金额
|
||||
paidPrice: number; // 已付金额
|
||||
paymentPrice: number; // 本次付款
|
||||
remark?: string; // 备注
|
||||
}
|
||||
|
||||
/** 付款单信息 */
|
||||
export interface FinancePayment {
|
||||
id?: number; // 付款单编号
|
||||
no: string; // 付款单号
|
||||
supplierId: number; // 供应商编号
|
||||
supplierName?: string; // 供应商名称
|
||||
paymentTime: Date; // 付款时间
|
||||
totalPrice: number; // 合计金额,单位:元
|
||||
discountPrice: number; // 优惠金额
|
||||
paymentPrice: number; // 实际付款金额
|
||||
status: number; // 状态
|
||||
remark: string; // 备注
|
||||
fileUrl?: string; // 附件
|
||||
accountId?: number; // 付款账户
|
||||
accountName?: string; // 账户名称
|
||||
financeUserId?: number; // 财务人员
|
||||
financeUserName?: string; // 财务人员姓名
|
||||
creator?: string; // 创建人
|
||||
creatorName?: string; // 创建人姓名
|
||||
items?: FinancePaymentItem[]; // 付款明细
|
||||
bizNo?: string; // 业务单号
|
||||
}
|
||||
|
||||
/** 付款单分页查询参数 */
|
||||
export interface FinancePaymentPageParams extends PageParam {
|
||||
no?: string;
|
||||
paymentTime?: [string, string];
|
||||
supplierId?: number;
|
||||
creator?: string;
|
||||
financeUserId?: number;
|
||||
accountId?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
bizNo?: string;
|
||||
}
|
||||
|
||||
/** 付款单状态更新参数 */
|
||||
|
||||
@@ -63,15 +63,19 @@ const [Form, formApi] = useVbenForm({
|
||||
schema: useFormSchema(formType.value),
|
||||
showDefaultActions: false,
|
||||
handleValuesChange: (values, changedFields) => {
|
||||
// 目的:同步到 item-form 组件,触发整体的价格计算
|
||||
if (formData.value && changedFields.includes('discountPrice')) {
|
||||
formData.value.discountPrice = values.discountPrice;
|
||||
// 重新计算实际付款
|
||||
formData.value.paymentPrice =
|
||||
formData.value.totalPrice - values.discountPrice;
|
||||
formApi.setValues({
|
||||
paymentPrice: formData.value.paymentPrice,
|
||||
});
|
||||
if (formData.value) {
|
||||
if (changedFields.includes('supplierId')) {
|
||||
formData.value.supplierId = values.supplierId;
|
||||
}
|
||||
// 目的:同步到 item-form 组件,触发整体的价格计算
|
||||
if (changedFields.includes('discountPrice')) {
|
||||
formData.value.discountPrice = values.discountPrice;
|
||||
formData.value.paymentPrice =
|
||||
formData.value.totalPrice - values.discountPrice;
|
||||
formApi.setValues({
|
||||
paymentPrice: formData.value.paymentPrice,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -164,15 +168,13 @@ const [Modal, modalApi] = useVbenModal({
|
||||
>
|
||||
<Form class="mx-3">
|
||||
<template #items>
|
||||
<div class="space-y-4">
|
||||
<ItemForm
|
||||
ref="itemFormRef"
|
||||
:items="formData?.items ?? []"
|
||||
:supplier-id="formData?.supplierId"
|
||||
:disabled="formType === 'detail'"
|
||||
@update:items="handleUpdateItems"
|
||||
/>
|
||||
</div>
|
||||
<ItemForm
|
||||
ref="itemFormRef"
|
||||
:items="formData?.items ?? []"
|
||||
:supplier-id="formData?.supplierId"
|
||||
:disabled="formType === 'detail'"
|
||||
@update:items="handleUpdateItems"
|
||||
/>
|
||||
</template>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
||||
@@ -13,6 +13,8 @@ import { Input, InputNumber, message } from 'ant-design-vue';
|
||||
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||
|
||||
import { useFormItemColumns } from '../data';
|
||||
import PurchaseInSelect from './purchase-in-select.vue';
|
||||
import SaleReturnSelect from './sale-return-select.vue';
|
||||
|
||||
interface Props {
|
||||
items?: ErpFinancePaymentApi.FinancePaymentItem[];
|
||||
@@ -22,6 +24,7 @@ interface Props {
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
items: () => [],
|
||||
supplierId: undefined,
|
||||
disabled: false,
|
||||
});
|
||||
|
||||
@@ -52,10 +55,9 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
gridOptions: {
|
||||
columns: useFormItemColumns(tableData.value),
|
||||
data: tableData.value,
|
||||
minHeight: 200,
|
||||
minHeight: 250,
|
||||
autoResize: true,
|
||||
border: true,
|
||||
showOverflow: true,
|
||||
rowConfig: {
|
||||
keyField: 'row_id',
|
||||
isHover: true,
|
||||
@@ -66,16 +68,6 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
toolbarConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
editConfig: {
|
||||
trigger: 'click',
|
||||
mode: 'cell',
|
||||
},
|
||||
editRules: {
|
||||
paymentPrice: [
|
||||
{ required: true, message: '本次付款不能为空' },
|
||||
{ type: 'number', min: 0, message: '本次付款不能小于0' },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -90,17 +82,15 @@ watch(
|
||||
tableData.value = [...items];
|
||||
await nextTick(); // 特殊:保证 gridApi 已经初始化
|
||||
await gridApi.grid.reloadData(tableData.value);
|
||||
// 更新表格列配置
|
||||
const columns = useFormItemColumns(tableData.value);
|
||||
await gridApi.grid.reloadColumn(columns);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
);
|
||||
|
||||
/** 初始化行数据 */
|
||||
const initRow = (item: any) => {
|
||||
if (!item.row_id) {
|
||||
item.row_id = Date.now() + Math.random();
|
||||
}
|
||||
};
|
||||
|
||||
/** 添加采购入库单 */
|
||||
const purchaseInSelectRef = ref();
|
||||
const handleOpenPurchaseIn = () => {
|
||||
@@ -114,14 +104,13 @@ const handleOpenPurchaseIn = () => {
|
||||
const handleAddPurchaseIn = (rows: ErpPurchaseInApi.PurchaseIn[]) => {
|
||||
rows.forEach((row) => {
|
||||
const newItem: ErpFinancePaymentApi.FinancePaymentItem = {
|
||||
row_id: Date.now() + Math.random(),
|
||||
bizId: row.id,
|
||||
bizType: ErpBizType.PURCHASE_IN,
|
||||
bizNo: row.no,
|
||||
totalPrice: row.totalPrice,
|
||||
paidPrice: row.paymentPrice,
|
||||
paymentPrice: row.totalPrice - row.paymentPrice,
|
||||
remark: '',
|
||||
remark: undefined,
|
||||
};
|
||||
tableData.value.push(newItem);
|
||||
});
|
||||
@@ -141,14 +130,13 @@ const handleOpenSaleReturn = () => {
|
||||
const handleAddSaleReturn = (rows: ErpPurchaseReturnApi.PurchaseReturn[]) => {
|
||||
rows.forEach((row) => {
|
||||
const newItem: ErpFinancePaymentApi.FinancePaymentItem = {
|
||||
row_id: Date.now() + Math.random(),
|
||||
bizId: row.id,
|
||||
bizType: ErpBizType.PURCHASE_RETURN,
|
||||
bizNo: row.no,
|
||||
totalPrice: -row.totalPrice,
|
||||
paidPrice: -row.refundPrice,
|
||||
paymentPrice: -row.totalPrice + row.refundPrice,
|
||||
remark: '',
|
||||
remark: undefined,
|
||||
};
|
||||
tableData.value.push(newItem);
|
||||
});
|
||||
@@ -157,7 +145,9 @@ const handleAddSaleReturn = (rows: ErpPurchaseReturnApi.PurchaseReturn[]) => {
|
||||
|
||||
/** 删除行 */
|
||||
const handleDelete = async (row: any) => {
|
||||
const index = tableData.value.findIndex((item) => item.row_id === row.row_id);
|
||||
const index = tableData.value.findIndex(
|
||||
(item) => item.bizId === row.bizId && item.bizType === row.bizType,
|
||||
);
|
||||
if (index !== -1) {
|
||||
tableData.value.splice(index, 1);
|
||||
emitUpdate();
|
||||
@@ -169,23 +159,18 @@ const emitUpdate = () => {
|
||||
emit('update:items', [...tableData.value]);
|
||||
};
|
||||
|
||||
/** 单元格编辑完成事件 */
|
||||
const handleEditClosed = async ({ row, column }: any) => {
|
||||
if (column.property === 'paymentPrice') {
|
||||
// 重新计算价格
|
||||
emitUpdate();
|
||||
// TODO @AI:增加一个 handleRowChange 方法;
|
||||
|
||||
// TODO @芋艿:待定!
|
||||
/** 初始化行数据 */
|
||||
const initRow = (item: any) => {
|
||||
if (!item.row_id) {
|
||||
item.row_id = Date.now() + Math.random();
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格事件 */
|
||||
const gridEvents = {
|
||||
editClosed: handleEditClosed,
|
||||
cellClick: ({ column }: any) => {
|
||||
if (column.title === '操作') {}
|
||||
},
|
||||
};
|
||||
|
||||
/** 校验表单 */
|
||||
// TODO @AI:一条有问题,就直接 throw
|
||||
const validate = async () => {
|
||||
const errors: string[] = [];
|
||||
|
||||
@@ -253,16 +238,20 @@ defineExpose({ validate });
|
||||
<div class="text-muted-foreground flex justify-between text-sm">
|
||||
<span class="text-foreground font-medium">合计:</span>
|
||||
<div class="flex space-x-4">
|
||||
<span>合计付款:
|
||||
{{ erpPriceInputFormatter(summaries.totalPrice) }}</span>
|
||||
<span>已付金额: {{ erpPriceInputFormatter(summaries.paidPrice) }}</span>
|
||||
<span>本次付款:
|
||||
{{ erpPriceInputFormatter(summaries.paymentPrice) }}</span>
|
||||
<span>
|
||||
合计付款:{{ erpPriceInputFormatter(summaries.totalPrice) }}
|
||||
</span>
|
||||
<span>
|
||||
已付金额:{{ erpPriceInputFormatter(summaries.paidPrice) }}
|
||||
</span>
|
||||
<span>
|
||||
本次付款:
|
||||
{{ erpPriceInputFormatter(summaries.paymentPrice) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加按钮放在底部 -->
|
||||
<!-- TODO @AI:换成 TableAction -->
|
||||
<div v-if="!disabled" class="mt-4 flex justify-center space-x-2">
|
||||
<a-button type="primary" @click="handleOpenPurchaseIn">
|
||||
+ 添加采购入库单
|
||||
|
||||
@@ -94,6 +94,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
{
|
||||
field: 'unPaymentPrice',
|
||||
title: '未付金额',
|
||||
// TODO @AI:芋艿,后续统一改;
|
||||
formatter: ({ row }) => {
|
||||
const unPaymentPrice = row.totalPrice - row.paymentPrice;
|
||||
return `${unPaymentPrice?.toFixed(2) || '0.00'}元`;
|
||||
@@ -154,43 +155,23 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
|
||||
/** 打开弹窗 */
|
||||
const openModal = (id: number) => {
|
||||
// 重置数据
|
||||
supplierId.value = id;
|
||||
open.value = true;
|
||||
selectedRows.value = [];
|
||||
// 重置表单并设置供应商ID
|
||||
// 查询列表
|
||||
gridApi.formApi?.resetForm();
|
||||
gridApi.formApi?.setValues({ supplierId: id });
|
||||
// 延迟查询,确保表单值已设置
|
||||
setTimeout(() => {
|
||||
gridApi.query();
|
||||
}, 100);
|
||||
gridApi.query();
|
||||
};
|
||||
|
||||
/** 确认选择 */
|
||||
/** 确认选择采购入库单 */
|
||||
const handleOk = () => {
|
||||
if (selectedRows.value.length === 0) {
|
||||
message.warning('请选择要添加的采购入库单');
|
||||
return;
|
||||
}
|
||||
|
||||
// 过滤已全部付款的单据
|
||||
const validRows = selectedRows.value.filter((row) => {
|
||||
const unPaymentPrice = row.totalPrice - row.paymentPrice;
|
||||
return unPaymentPrice > 0;
|
||||
});
|
||||
|
||||
if (validRows.length === 0) {
|
||||
message.warning('所选的入库单已全部付款,无需再付款');
|
||||
return;
|
||||
}
|
||||
|
||||
if (validRows.length < selectedRows.value.length) {
|
||||
message.warning(
|
||||
`已过滤${selectedRows.value.length - validRows.length}个已全部付款的入库单`,
|
||||
);
|
||||
}
|
||||
|
||||
emit('success', validRows);
|
||||
emit('success', selectedRows.value);
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
@@ -199,14 +180,13 @@ defineExpose({ open: openModal });
|
||||
|
||||
<template>
|
||||
<Modal
|
||||
class="!w-[70vw]"
|
||||
class="!w-[50vw]"
|
||||
v-model:open="open"
|
||||
title="选择采购入库单"
|
||||
@ok="handleOk"
|
||||
:width="1000"
|
||||
>
|
||||
<Grid
|
||||
class="max-h-[500px]"
|
||||
class="max-h-[600px]"
|
||||
table-title="采购入库单列表(仅展示可付款的单据)"
|
||||
/>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user