feat:【ele】【erp】purchase 的迁移(40%)- in
This commit is contained in:
@@ -503,7 +503,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 220,
|
width: 260,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: { default: 'actions' },
|
slots: { default: 'actions' },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
label: row.status === 10 ? '审批' : '反审批',
|
label: row.status === 10 ? '审批' : '反审批',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.AUDIT,
|
||||||
auth: ['erp:purchase-in:update-status'],
|
auth: ['erp:purchase-in:update-status'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
||||||
@@ -210,6 +211,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
label: $t('common.delete'),
|
label: $t('common.delete'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
danger: true,
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
auth: ['erp:purchase-in:delete'],
|
auth: ['erp:purchase-in:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
||||||
|
|||||||
@@ -434,7 +434,7 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 220,
|
width: 260,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: { default: 'actions' },
|
slots: { default: 'actions' },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
label: row.status === 10 ? '审批' : '反审批',
|
label: row.status === 10 ? '审批' : '反审批',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.AUDIT,
|
||||||
auth: ['erp:purchase-order:update-status'],
|
auth: ['erp:purchase-order:update-status'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
||||||
@@ -210,6 +211,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
label: $t('common.delete'),
|
label: $t('common.delete'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
danger: true,
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
auth: ['erp:purchase-order:delete'],
|
auth: ['erp:purchase-order:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
||||||
|
|||||||
@@ -490,12 +490,13 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
width: 220,
|
width: 260,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
slots: { default: 'actions' },
|
slots: { default: 'actions' },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列表的搜索表单 */
|
/** 列表的搜索表单 */
|
||||||
export function useOrderGridFormSchema(): VbenFormSchema[] {
|
export function useOrderGridFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
{
|
{
|
||||||
label: row.status === 10 ? '审批' : '反审批',
|
label: row.status === 10 ? '审批' : '反审批',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
|
icon: ACTION_ICON.AUDIT,
|
||||||
auth: ['erp:purchase-return:update-status'],
|
auth: ['erp:purchase-return:update-status'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
||||||
@@ -210,6 +211,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
|||||||
label: $t('common.delete'),
|
label: $t('common.delete'),
|
||||||
type: 'link',
|
type: 'link',
|
||||||
danger: true,
|
danger: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
auth: ['erp:purchase-return:delete'],
|
auth: ['erp:purchase-return:delete'],
|
||||||
popConfirm: {
|
popConfirm: {
|
||||||
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
||||||
|
|||||||
622
apps/web-ele/src/views/erp/purchase/in/data.ts
Normal file
622
apps/web-ele/src/views/erp/purchase/in/data.ts
Normal file
@@ -0,0 +1,622 @@
|
|||||||
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { DICT_TYPE } from '@vben/constants';
|
||||||
|
import { getDictOptions } from '@vben/hooks';
|
||||||
|
import { erpNumberFormatter, erpPriceInputFormatter } from '@vben/utils';
|
||||||
|
|
||||||
|
import { z } from '#/adapter/form';
|
||||||
|
import { getAccountSimpleList } from '#/api/erp/finance/account';
|
||||||
|
import { getProductSimpleList } from '#/api/erp/product/product';
|
||||||
|
import { getSupplierSimpleList } from '#/api/erp/purchase/supplier';
|
||||||
|
import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
|
||||||
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
|
import { getRangePickerDefaultProps } from '#/utils';
|
||||||
|
|
||||||
|
/** 表单的配置项 */
|
||||||
|
export function useFormSchema(formType: string): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'no',
|
||||||
|
label: '入库单号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '系统自动生成',
|
||||||
|
disabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'inTime',
|
||||||
|
label: '入库时间',
|
||||||
|
component: 'DatePicker',
|
||||||
|
componentProps: {
|
||||||
|
disabled: formType === 'detail',
|
||||||
|
placeholder: '选择入库时间',
|
||||||
|
showTime: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm:ss',
|
||||||
|
valueFormat: 'x',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'orderNo',
|
||||||
|
label: '关联订单',
|
||||||
|
component: 'Input',
|
||||||
|
formItemClass: 'col-span-1',
|
||||||
|
rules: 'required',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择关联订单',
|
||||||
|
disabled: formType === 'detail',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'supplierId',
|
||||||
|
label: '供应商',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
disabled: true,
|
||||||
|
placeholder: '请选择供应商',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getSupplierSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Textarea',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入备注',
|
||||||
|
autoSize: { minRows: 1, maxRows: 1 },
|
||||||
|
disabled: formType === 'detail',
|
||||||
|
},
|
||||||
|
formItemClass: 'col-span-2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'fileUrl',
|
||||||
|
label: '附件',
|
||||||
|
component: 'FileUpload',
|
||||||
|
componentProps: {
|
||||||
|
maxNumber: 1,
|
||||||
|
maxSize: 10,
|
||||||
|
accept: [
|
||||||
|
'pdf',
|
||||||
|
'doc',
|
||||||
|
'docx',
|
||||||
|
'xls',
|
||||||
|
'xlsx',
|
||||||
|
'txt',
|
||||||
|
'jpg',
|
||||||
|
'jpeg',
|
||||||
|
'png',
|
||||||
|
],
|
||||||
|
showDescription: formType !== 'detail',
|
||||||
|
disabled: formType === 'detail',
|
||||||
|
},
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'items',
|
||||||
|
label: '入库产品清单',
|
||||||
|
component: 'Input',
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountPercent',
|
||||||
|
label: '优惠率(%)',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入优惠率',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
precision: 2,
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
rules: z.number().min(0).optional(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountPrice',
|
||||||
|
label: '付款优惠',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '付款优惠',
|
||||||
|
precision: 2,
|
||||||
|
formatter: erpPriceInputFormatter,
|
||||||
|
disabled: true,
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountedPrice',
|
||||||
|
label: '优惠后金额',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '优惠后金额',
|
||||||
|
precision: 2,
|
||||||
|
formatter: erpPriceInputFormatter,
|
||||||
|
disabled: true,
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['totalPrice', 'otherPrice'],
|
||||||
|
componentProps: (values) => {
|
||||||
|
const totalPrice = values.totalPrice || 0;
|
||||||
|
const otherPrice = values.otherPrice || 0;
|
||||||
|
values.discountedPrice = totalPrice - otherPrice;
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'otherPrice',
|
||||||
|
label: '其他费用',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
disabled: formType === 'detail',
|
||||||
|
placeholder: '请输入其他费用',
|
||||||
|
precision: 2,
|
||||||
|
formatter: erpPriceInputFormatter,
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'accountId',
|
||||||
|
label: '结算账户',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择结算账户',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getAccountSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'totalPrice',
|
||||||
|
label: '应付金额',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
precision: 2,
|
||||||
|
min: 0,
|
||||||
|
disabled: true,
|
||||||
|
controlsPosition: 'right',
|
||||||
|
class: '!w-full',
|
||||||
|
},
|
||||||
|
rules: z.number().min(0).optional(),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单的明细表格列 */
|
||||||
|
export function useFormItemColumns(
|
||||||
|
formData?: any[],
|
||||||
|
): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{ type: 'seq', title: '序号', minWidth: 50, fixed: 'left' },
|
||||||
|
{
|
||||||
|
field: 'warehouseId',
|
||||||
|
title: '仓库名称',
|
||||||
|
minWidth: 200,
|
||||||
|
slots: { default: 'warehouseId' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productId',
|
||||||
|
title: '产品名称',
|
||||||
|
minWidth: 200,
|
||||||
|
slots: { default: 'productId' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'stockCount',
|
||||||
|
title: '库存',
|
||||||
|
minWidth: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productBarCode',
|
||||||
|
title: '条码',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productUnitName',
|
||||||
|
title: '单位',
|
||||||
|
minWidth: 80,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'remark',
|
||||||
|
title: '备注',
|
||||||
|
minWidth: 150,
|
||||||
|
slots: { default: 'remark' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalCount',
|
||||||
|
title: '原数量',
|
||||||
|
formatter: 'formatAmount3',
|
||||||
|
minWidth: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
visible: formData && formData[0]?.inCount !== undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'inCount',
|
||||||
|
title: '已入库',
|
||||||
|
formatter: 'formatAmount3',
|
||||||
|
minWidth: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
visible: formData && formData[0]?.returnCount !== undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'count',
|
||||||
|
title: '数量',
|
||||||
|
minWidth: 120,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'count' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productPrice',
|
||||||
|
title: '产品单价',
|
||||||
|
fixed: 'right',
|
||||||
|
minWidth: 120,
|
||||||
|
slots: { default: 'productPrice' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalProductPrice',
|
||||||
|
fixed: 'right',
|
||||||
|
title: '产品金额',
|
||||||
|
minWidth: 120,
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixed: 'right',
|
||||||
|
field: 'taxPercent',
|
||||||
|
title: '税率(%)',
|
||||||
|
minWidth: 105,
|
||||||
|
slots: { default: 'taxPercent' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fixed: 'right',
|
||||||
|
field: 'taxPrice',
|
||||||
|
title: '税额',
|
||||||
|
minWidth: 120,
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
fixed: 'right',
|
||||||
|
title: '合计金额',
|
||||||
|
minWidth: 120,
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 50,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的搜索表单 */
|
||||||
|
export function useGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'no',
|
||||||
|
label: '入库单号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入入库单号',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'productId',
|
||||||
|
label: '产品',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择产品',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getProductSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'inTime',
|
||||||
|
label: '入库时间',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'supplierId',
|
||||||
|
label: '供应商',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择供应商',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getSupplierSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'warehouseId',
|
||||||
|
label: '仓库',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择仓库',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getWarehouseSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'creator',
|
||||||
|
label: '创建人',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择创建人',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getSimpleUserList,
|
||||||
|
labelField: 'nickname',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'orderNo',
|
||||||
|
label: '关联订单',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入关联订单号',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'accountId',
|
||||||
|
label: '结算账户',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择结算账户',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getAccountSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'paymentStatus',
|
||||||
|
label: '付款状态',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{ label: '未付款', value: 0 },
|
||||||
|
{ label: '部分付款', value: 1 },
|
||||||
|
{ label: '全部付款', value: 2 },
|
||||||
|
],
|
||||||
|
placeholder: '请选择付款状态',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'status',
|
||||||
|
label: '审批状态',
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
options: getDictOptions(DICT_TYPE.ERP_AUDIT_STATUS, 'number'),
|
||||||
|
placeholder: '请选择审批状态',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'remark',
|
||||||
|
label: '备注',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入备注',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的字段 */
|
||||||
|
export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'checkbox',
|
||||||
|
width: 50,
|
||||||
|
fixed: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'no',
|
||||||
|
title: '入库单号',
|
||||||
|
width: 200,
|
||||||
|
fixed: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productNames',
|
||||||
|
title: '产品信息',
|
||||||
|
showOverflow: 'tooltip',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'supplierName',
|
||||||
|
title: '供应商',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'inTime',
|
||||||
|
title: '入库时间',
|
||||||
|
width: 160,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'creatorName',
|
||||||
|
title: '创建人',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalCount',
|
||||||
|
title: '总数量',
|
||||||
|
formatter: 'formatAmount3',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
title: '应付金额',
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'paymentPrice',
|
||||||
|
title: '已付金额',
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'unPaymentPrice',
|
||||||
|
title: '未付金额',
|
||||||
|
formatter: ({ row }) => {
|
||||||
|
return `${erpNumberFormatter(row.totalPrice - row.paymentPrice, 2)}元`;
|
||||||
|
},
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '审批状态',
|
||||||
|
minWidth: 120,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.ERP_AUDIT_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 260,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的搜索表单 */
|
||||||
|
export function useOrderGridFormSchema(): VbenFormSchema[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'no',
|
||||||
|
label: '订单单号',
|
||||||
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请输入订单单号',
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'productId',
|
||||||
|
label: '产品',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
placeholder: '请选择产品',
|
||||||
|
allowClear: true,
|
||||||
|
showSearch: true,
|
||||||
|
api: getProductSimpleList,
|
||||||
|
labelField: 'name',
|
||||||
|
valueField: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'orderTime',
|
||||||
|
label: '订单时间',
|
||||||
|
component: 'RangePicker',
|
||||||
|
componentProps: {
|
||||||
|
...getRangePickerDefaultProps(),
|
||||||
|
allowClear: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表的字段 */
|
||||||
|
export function useOrderGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
width: 50,
|
||||||
|
fixed: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'no',
|
||||||
|
title: '订单单号',
|
||||||
|
width: 200,
|
||||||
|
fixed: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productNames',
|
||||||
|
title: '产品信息',
|
||||||
|
showOverflow: 'tooltip',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'supplierName',
|
||||||
|
title: '供应商',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'orderTime',
|
||||||
|
title: '订单时间',
|
||||||
|
width: 160,
|
||||||
|
formatter: 'formatDate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'creatorName',
|
||||||
|
title: '创建人',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalCount',
|
||||||
|
title: '总数量',
|
||||||
|
formatter: 'formatAmount3',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'inCount',
|
||||||
|
title: '入库数量',
|
||||||
|
formatter: 'formatAmount3',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalProductPrice',
|
||||||
|
title: '金额合计',
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
title: '含税金额',
|
||||||
|
formatter: 'formatAmount2',
|
||||||
|
minWidth: 120,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
226
apps/web-ele/src/views/erp/purchase/in/index.vue
Normal file
226
apps/web-ele/src/views/erp/purchase/in/index.vue
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { ErpPurchaseInApi } from '#/api/erp/purchase/in';
|
||||||
|
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { DocAlert, Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
|
import { ElLoading, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import {
|
||||||
|
deletePurchaseIn,
|
||||||
|
exportPurchaseIn,
|
||||||
|
getPurchaseInPage,
|
||||||
|
updatePurchaseInStatus,
|
||||||
|
} from '#/api/erp/purchase/in';
|
||||||
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
|
import { useGridColumns, useGridFormSchema } from './data';
|
||||||
|
import Form from './modules/form.vue';
|
||||||
|
|
||||||
|
/** ERP 采购入库列表 */
|
||||||
|
defineOptions({ name: 'ErpPurchaseIn' });
|
||||||
|
|
||||||
|
const [FormModal, formModalApi] = useVbenModal({
|
||||||
|
connectedComponent: Form,
|
||||||
|
destroyOnClose: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 刷新表格 */
|
||||||
|
function handleRefresh() {
|
||||||
|
gridApi.query();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出表格 */
|
||||||
|
async function handleExport() {
|
||||||
|
const data = await exportPurchaseIn(await gridApi.formApi.getValues());
|
||||||
|
downloadFileFromBlobPart({ fileName: '采购入库.xls', source: data });
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 新增采购入库 */
|
||||||
|
function handleCreate() {
|
||||||
|
formModalApi.setData({ type: 'create' }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑采购入库 */
|
||||||
|
function handleEdit(row: ErpPurchaseInApi.PurchaseIn) {
|
||||||
|
formModalApi.setData({ type: 'edit', id: row.id }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 删除采购入库 */
|
||||||
|
async function handleDelete(ids: number[]) {
|
||||||
|
const loadingInstance = ElLoading.service({
|
||||||
|
text: $t('ui.actionMessage.deleting'),
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await deletePurchaseIn(ids);
|
||||||
|
ElMessage.success($t('ui.actionMessage.deleteSuccess'));
|
||||||
|
handleRefresh();
|
||||||
|
} finally {
|
||||||
|
loadingInstance.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 审批/反审批操作 */
|
||||||
|
async function handleUpdateStatus(
|
||||||
|
row: ErpPurchaseInApi.PurchaseIn,
|
||||||
|
status: number,
|
||||||
|
) {
|
||||||
|
const loadingInstance = ElLoading.service({
|
||||||
|
text: `确定${status === 20 ? '审批' : '反审批'}该订单吗?`,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await updatePurchaseInStatus(row.id!, status);
|
||||||
|
ElMessage.success(`${status === 20 ? '审批' : '反审批'}成功`);
|
||||||
|
handleRefresh();
|
||||||
|
} finally {
|
||||||
|
loadingInstance.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkedIds = ref<number[]>([]);
|
||||||
|
function handleRowCheckboxChange({
|
||||||
|
records,
|
||||||
|
}: {
|
||||||
|
records: ErpPurchaseInApi.PurchaseIn[];
|
||||||
|
}) {
|
||||||
|
checkedIds.value = records.map((item) => item.id!);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查看详情 */
|
||||||
|
function handleDetail(row: ErpPurchaseInApi.PurchaseIn) {
|
||||||
|
formModalApi.setData({ type: 'detail', id: row.id }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useGridColumns(),
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getPurchaseInPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<ErpPurchaseInApi.PurchaseIn>,
|
||||||
|
gridEvents: {
|
||||||
|
checkboxAll: handleRowCheckboxChange,
|
||||||
|
checkboxChange: handleRowCheckboxChange,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Page auto-content-height>
|
||||||
|
<template #doc>
|
||||||
|
<DocAlert
|
||||||
|
title="【采购】采购订单、入库、退货"
|
||||||
|
url="https://doc.iocoder.cn/erp/purchase/"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<FormModal @success="handleRefresh" />
|
||||||
|
<Grid table-title="采购入库列表">
|
||||||
|
<template #toolbar-tools>
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('ui.actionTitle.create', ['采购入库']),
|
||||||
|
type: 'primary',
|
||||||
|
icon: ACTION_ICON.ADD,
|
||||||
|
auth: ['erp:purchase-in:create'],
|
||||||
|
onClick: handleCreate,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('ui.actionTitle.export'),
|
||||||
|
type: 'primary',
|
||||||
|
icon: ACTION_ICON.DOWNLOAD,
|
||||||
|
auth: ['erp:purchase-in:export'],
|
||||||
|
onClick: handleExport,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '批量删除',
|
||||||
|
type: 'danger',
|
||||||
|
disabled: isEmpty(checkedIds),
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['erp:purchase-in:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: `是否删除所选中数据?`,
|
||||||
|
confirm: handleDelete.bind(null, checkedIds),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.detail'),
|
||||||
|
type: 'primary',
|
||||||
|
link: true,
|
||||||
|
icon: ACTION_ICON.VIEW,
|
||||||
|
auth: ['erp:purchase-in:query'],
|
||||||
|
onClick: handleDetail.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.edit'),
|
||||||
|
type: 'primary',
|
||||||
|
link: true,
|
||||||
|
icon: ACTION_ICON.EDIT,
|
||||||
|
auth: ['erp:purchase-in:update'],
|
||||||
|
ifShow: () => row.status !== 20,
|
||||||
|
onClick: handleEdit.bind(null, row),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: row.status === 10 ? '审批' : '反审批',
|
||||||
|
type: 'primary',
|
||||||
|
link: true,
|
||||||
|
icon: ACTION_ICON.AUDIT,
|
||||||
|
auth: ['erp:purchase-in:update-status'],
|
||||||
|
popConfirm: {
|
||||||
|
title: `确认${row.status === 10 ? '审批' : '反审批'}${row.no}吗?`,
|
||||||
|
confirm: handleUpdateStatus.bind(
|
||||||
|
null,
|
||||||
|
row,
|
||||||
|
row.status === 10 ? 20 : 10,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'danger',
|
||||||
|
link: true,
|
||||||
|
icon: ACTION_ICON.DELETE,
|
||||||
|
auth: ['erp:purchase-in:delete'],
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.no]),
|
||||||
|
confirm: handleDelete.bind(null, [row.id!]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</Page>
|
||||||
|
</template>
|
||||||
310
apps/web-ele/src/views/erp/purchase/in/modules/item-form.vue
Normal file
310
apps/web-ele/src/views/erp/purchase/in/modules/item-form.vue
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { ErpPurchaseInApi } from '#/api/erp/purchase/in';
|
||||||
|
|
||||||
|
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import {
|
||||||
|
erpCountInputFormatter,
|
||||||
|
erpPriceInputFormatter,
|
||||||
|
erpPriceMultiply,
|
||||||
|
} from '@vben/utils';
|
||||||
|
|
||||||
|
import { ElInput, ElInputNumber, ElSelect } from 'element-plus';
|
||||||
|
|
||||||
|
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getProductSimpleList } from '#/api/erp/product/product';
|
||||||
|
import { getWarehouseStockCount } from '#/api/erp/stock/stock';
|
||||||
|
import { getWarehouseSimpleList } from '#/api/erp/stock/warehouse';
|
||||||
|
|
||||||
|
import { useFormItemColumns } from '../data';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
items?: ErpPurchaseInApi.PurchaseInItem[];
|
||||||
|
disabled?: boolean;
|
||||||
|
discountPercent?: number;
|
||||||
|
otherPrice?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
items: () => [],
|
||||||
|
disabled: false,
|
||||||
|
discountPercent: 0,
|
||||||
|
otherPrice: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits([
|
||||||
|
'update:items',
|
||||||
|
'update:discount-price',
|
||||||
|
'update:other-price',
|
||||||
|
'update:total-price',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tableData = ref<ErpPurchaseInApi.PurchaseInItem[]>([]); // 表格数据
|
||||||
|
const productOptions = ref<any[]>([]); // 产品下拉选项
|
||||||
|
const warehouseOptions = ref<any[]>([]); // 仓库下拉选项
|
||||||
|
|
||||||
|
/** 获取表格合计数据 */
|
||||||
|
const summaries = computed(() => {
|
||||||
|
return {
|
||||||
|
count: tableData.value.reduce((sum, item) => sum + (item.count || 0), 0),
|
||||||
|
totalProductPrice: tableData.value.reduce(
|
||||||
|
(sum, item) => sum + (item.totalProductPrice || 0),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
taxPrice: tableData.value.reduce(
|
||||||
|
(sum, item) => sum + (item.taxPrice || 0),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
totalPrice: tableData.value.reduce(
|
||||||
|
(sum, item) => sum + (item.totalPrice || 0),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 表格配置 */
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: useFormItemColumns(tableData.value),
|
||||||
|
data: tableData.value,
|
||||||
|
minHeight: 250,
|
||||||
|
autoResize: true,
|
||||||
|
border: true,
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'seq',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 监听外部传入的列数据 */
|
||||||
|
watch(
|
||||||
|
() => props.items,
|
||||||
|
async (items) => {
|
||||||
|
if (!items) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
items.forEach((item) => initRow(item));
|
||||||
|
tableData.value = [...items];
|
||||||
|
await nextTick(); // 特殊:保证 gridApi 已经初始化
|
||||||
|
await gridApi.grid.reloadData(tableData.value);
|
||||||
|
// 更新表格列配置(目的:原数量、已入库动态列)
|
||||||
|
const columns = useFormItemColumns(tableData.value);
|
||||||
|
await gridApi.grid.reloadColumn(columns || []);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 计算 discountPrice、otherPrice、totalPrice 价格 */
|
||||||
|
watch(
|
||||||
|
() => [tableData.value, props.discountPercent, props.otherPrice],
|
||||||
|
() => {
|
||||||
|
if (!tableData.value || tableData.value.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const totalPrice = tableData.value.reduce(
|
||||||
|
(prev, curr) => prev + (curr.totalPrice || 0),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
const discountPrice =
|
||||||
|
props.discountPercent === null
|
||||||
|
? 0
|
||||||
|
: erpPriceMultiply(totalPrice, props.discountPercent / 100);
|
||||||
|
const discountedPrice = totalPrice - discountPrice!;
|
||||||
|
const finalTotalPrice = discountedPrice + (props.otherPrice || 0);
|
||||||
|
|
||||||
|
// 通知父组件更新
|
||||||
|
emit('update:discount-price', discountPrice);
|
||||||
|
emit('update:other-price', props.otherPrice || 0);
|
||||||
|
emit('update:total-price', finalTotalPrice);
|
||||||
|
},
|
||||||
|
{ deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 处理删除 */
|
||||||
|
function handleDelete(row: ErpPurchaseInApi.PurchaseInItem) {
|
||||||
|
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||||
|
if (index !== -1) {
|
||||||
|
tableData.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
// 通知父组件更新
|
||||||
|
emit('update:items', [...tableData.value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理仓库变更 */
|
||||||
|
async function handleWarehouseChange(row: ErpPurchaseInApi.PurchaseInItem) {
|
||||||
|
const stockCount = await getWarehouseStockCount({
|
||||||
|
productId: row.productId!,
|
||||||
|
warehouseId: row.warehouseId!,
|
||||||
|
});
|
||||||
|
row.stockCount = stockCount || 0;
|
||||||
|
handleRowChange(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 处理行数据变更 */
|
||||||
|
function handleRowChange(row: any) {
|
||||||
|
const index = tableData.value.findIndex((item) => item.seq === row.seq);
|
||||||
|
if (index === -1) {
|
||||||
|
tableData.value.push(row);
|
||||||
|
} else {
|
||||||
|
tableData.value[index] = row;
|
||||||
|
}
|
||||||
|
emit('update:items', [...tableData.value]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 初始化行数据 */
|
||||||
|
function initRow(row: ErpPurchaseInApi.PurchaseInItem) {
|
||||||
|
if (row.productPrice && row.count) {
|
||||||
|
row.totalProductPrice = erpPriceMultiply(row.productPrice, row.count) ?? 0;
|
||||||
|
row.taxPrice =
|
||||||
|
erpPriceMultiply(row.totalProductPrice, (row.taxPercent || 0) / 100) ?? 0;
|
||||||
|
row.totalPrice = row.totalProductPrice + row.taxPrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表单校验 */
|
||||||
|
function validate() {
|
||||||
|
for (let i = 0; i < tableData.value.length; i++) {
|
||||||
|
const item = tableData.value[i];
|
||||||
|
if (item) {
|
||||||
|
if (!item.warehouseId) {
|
||||||
|
throw new Error(`第 ${i + 1} 行:仓库不能为空`);
|
||||||
|
}
|
||||||
|
if (!item.count || item.count <= 0) {
|
||||||
|
throw new Error(`第 ${i + 1} 行:产品数量不能为空`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
validate,
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
onMounted(async () => {
|
||||||
|
productOptions.value = await getProductSimpleList();
|
||||||
|
warehouseOptions.value = await getWarehouseSimpleList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Grid class="w-full">
|
||||||
|
<template #warehouseId="{ row }">
|
||||||
|
<ElSelect
|
||||||
|
v-model="row.warehouseId"
|
||||||
|
:disabled="disabled"
|
||||||
|
placeholder="请选择仓库"
|
||||||
|
filterable
|
||||||
|
class="w-full"
|
||||||
|
@change="handleWarehouseChange(row)"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in warehouseOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
<template #productId="{ row }">
|
||||||
|
<ElSelect
|
||||||
|
v-model="row.productId"
|
||||||
|
disabled
|
||||||
|
placeholder="请选择产品"
|
||||||
|
filterable
|
||||||
|
class="w-full"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in productOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</ElSelect>
|
||||||
|
</template>
|
||||||
|
<template #count="{ row }">
|
||||||
|
<ElInputNumber
|
||||||
|
v-if="!disabled"
|
||||||
|
v-model="row.count"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
controls-position="right"
|
||||||
|
class="!w-full"
|
||||||
|
@change="handleRowChange(row)"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ erpCountInputFormatter(row.count) || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
<template #productPrice="{ row }">
|
||||||
|
<ElInputNumber
|
||||||
|
v-if="!disabled"
|
||||||
|
v-model="row.productPrice"
|
||||||
|
:min="0"
|
||||||
|
:precision="2"
|
||||||
|
controls-position="right"
|
||||||
|
class="!w-full"
|
||||||
|
@change="handleRowChange(row)"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ erpPriceInputFormatter(row.productPrice) || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
<template #remark="{ row }">
|
||||||
|
<ElInput v-if="!disabled" v-model="row.remark" class="w-full" />
|
||||||
|
<span v-else>{{ row.remark || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
<template #taxPercent="{ row }">
|
||||||
|
<ElInputNumber
|
||||||
|
v-if="!disabled"
|
||||||
|
v-model="row.taxPercent"
|
||||||
|
:min="0"
|
||||||
|
:max="100"
|
||||||
|
:precision="2"
|
||||||
|
controls-position="right"
|
||||||
|
class="!w-full"
|
||||||
|
@change="handleRowChange(row)"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ row.taxPercent || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
v-if="!disabled"
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
type: 'danger',
|
||||||
|
link: true,
|
||||||
|
popConfirm: {
|
||||||
|
title: '确认删除该产品吗?',
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #bottom>
|
||||||
|
<div class="border-border bg-muted mt-2 rounded border p-2">
|
||||||
|
<div class="text-muted-foreground flex justify-between text-sm">
|
||||||
|
<span class="text-foreground font-medium">合计:</span>
|
||||||
|
<div class="flex space-x-4">
|
||||||
|
<span>数量:{{ erpCountInputFormatter(summaries.count) }}</span>
|
||||||
|
<span>
|
||||||
|
金额:{{ erpPriceInputFormatter(summaries.totalProductPrice) }}
|
||||||
|
</span>
|
||||||
|
<span>税额:{{ erpPriceInputFormatter(summaries.taxPrice) }}</span>
|
||||||
|
<span>
|
||||||
|
税额合计:{{ erpPriceInputFormatter(summaries.totalPrice) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { ErpPurchaseOrderApi } from '#/api/erp/purchase/order';
|
||||||
|
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { ElDialog, ElInput, ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getPurchaseOrderPage } from '#/api/erp/purchase/order';
|
||||||
|
|
||||||
|
import { useOrderGridColumns, useOrderGridFormSchema } from '../data';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
orderNo: {
|
||||||
|
type: String,
|
||||||
|
default: () => undefined,
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
'update:order': [order: ErpPurchaseOrderApi.PurchaseOrder];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const order = ref<ErpPurchaseOrderApi.PurchaseOrder>(); // 选择的采购订单
|
||||||
|
const open = ref<boolean>(false); // 选择采购订单弹窗是否打开
|
||||||
|
|
||||||
|
/** 表格配置 */
|
||||||
|
const [Grid] = useVbenVxeGrid({
|
||||||
|
formOptions: {
|
||||||
|
schema: useOrderGridFormSchema(),
|
||||||
|
},
|
||||||
|
gridOptions: {
|
||||||
|
columns: useOrderGridColumns(),
|
||||||
|
height: 'auto',
|
||||||
|
keepSource: true,
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async ({ page }, formValues) => {
|
||||||
|
return await getPurchaseOrderPage({
|
||||||
|
pageNo: page.currentPage,
|
||||||
|
pageSize: page.pageSize,
|
||||||
|
inEnable: true,
|
||||||
|
...formValues,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
trigger: 'row',
|
||||||
|
highlight: true,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
refresh: true,
|
||||||
|
search: true,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<ErpPurchaseOrderApi.PurchaseOrder>,
|
||||||
|
gridEvents: {
|
||||||
|
radioChange: ({ row }: { row: ErpPurchaseOrderApi.PurchaseOrder }) => {
|
||||||
|
handleSelectOrder(row);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 选择采购订单 */
|
||||||
|
function handleSelectOrder(selectOrder: ErpPurchaseOrderApi.PurchaseOrder) {
|
||||||
|
order.value = selectOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 确认选择采购订单 */
|
||||||
|
function handleOk() {
|
||||||
|
if (!order.value) {
|
||||||
|
ElMessage.warning('请选择一个采购订单');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit('update:order', order.value);
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ElInput
|
||||||
|
readonly
|
||||||
|
:model-value="orderNo"
|
||||||
|
:disabled="disabled"
|
||||||
|
@click="() => !disabled && (open = true)"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<div>
|
||||||
|
<IconifyIcon
|
||||||
|
class="h-full w-6 cursor-pointer"
|
||||||
|
icon="ant-design:setting-outlined"
|
||||||
|
:style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
|
||||||
|
@click="() => !disabled && (open = true)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ElInput>
|
||||||
|
<ElDialog
|
||||||
|
v-model="open"
|
||||||
|
title="选择关联订单"
|
||||||
|
width="50%"
|
||||||
|
@close="open = false"
|
||||||
|
:append-to-body="true"
|
||||||
|
>
|
||||||
|
<Grid class="max-h-[600px]" table-title="采购订单列表(仅展示可退货)" />
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="open = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleOk">确定</el-button>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user