feat: product list
parent
082bb7167f
commit
acd0677f81
|
@ -90,6 +90,12 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
valueFormat: 'x',
|
valueFormat: 'x',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'product',
|
||||||
|
label: '产品清单',
|
||||||
|
component: 'Input',
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'totalProductPrice',
|
fieldName: 'totalProductPrice',
|
||||||
label: '产品总金额',
|
label: '产品总金额',
|
||||||
|
|
|
@ -13,7 +13,10 @@ import {
|
||||||
getBusiness,
|
getBusiness,
|
||||||
updateBusiness,
|
updateBusiness,
|
||||||
} from '#/api/crm/business';
|
} from '#/api/crm/business';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { erpPriceMultiply } from '#/utils';
|
||||||
|
import { ProductEditTable } from '#/views/crm/product';
|
||||||
|
|
||||||
import { useFormSchema } from '../data';
|
import { useFormSchema } from '../data';
|
||||||
|
|
||||||
|
@ -25,15 +28,37 @@ const getTitle = computed(() => {
|
||||||
: $t('ui.actionTitle.create', ['商机']);
|
: $t('ui.actionTitle.create', ['商机']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleUpdateProducts(products: any) {
|
||||||
|
formData.value = modalApi.getData<CrmBusinessApi.Business>();
|
||||||
|
formData.value!.products = products;
|
||||||
|
if (formData.value) {
|
||||||
|
const totalProductPrice =
|
||||||
|
formData.value.products?.reduce(
|
||||||
|
(prev, curr) => prev + curr.totalPrice,
|
||||||
|
0,
|
||||||
|
) ?? 0;
|
||||||
|
const discountPercent = formData.value.discountPercent;
|
||||||
|
const discountPrice =
|
||||||
|
discountPercent === null
|
||||||
|
? 0
|
||||||
|
: erpPriceMultiply(totalProductPrice, discountPercent / 100);
|
||||||
|
const totalPrice = totalProductPrice - (discountPrice ?? 0);
|
||||||
|
formData.value!.totalProductPrice = totalProductPrice;
|
||||||
|
formData.value!.totalPrice = totalPrice;
|
||||||
|
formApi.setValues(formData.value!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
},
|
},
|
||||||
formItemClass: 'col-span-2',
|
|
||||||
labelWidth: 120,
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
layout: 'horizontal',
|
// 一共3列
|
||||||
|
wrapperClass: 'grid-cols-3',
|
||||||
|
layout: 'vertical',
|
||||||
schema: useFormSchema(),
|
schema: useFormSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
@ -47,6 +72,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as CrmBusinessApi.Business;
|
const data = (await formApi.getValues()) as CrmBusinessApi.Business;
|
||||||
|
data.products = formData.value?.products;
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id ? updateBusiness(data) : createBusiness(data));
|
await (formData.value?.id ? updateBusiness(data) : createBusiness(data));
|
||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
|
@ -80,7 +106,17 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal :title="getTitle" class="w-[40%]">
|
<Modal :title="getTitle" class="w-[50%]">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4">
|
||||||
|
<template #product="slotProps">
|
||||||
|
<ProductEditTable
|
||||||
|
v-bind="slotProps"
|
||||||
|
class="w-full"
|
||||||
|
:products="formData?.products ?? []"
|
||||||
|
:biz-type="BizTypeEnum.CRM_BUSINESS"
|
||||||
|
@update:products="handleUpdateProducts"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,22 +1,32 @@
|
||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
|
||||||
|
import { z } from '#/adapter/form';
|
||||||
import { getSimpleBusinessList } from '#/api/crm/business';
|
import { getSimpleBusinessList } from '#/api/crm/business';
|
||||||
import { getSimpleContactList } from '#/api/crm/contact';
|
import { getSimpleContactList } from '#/api/crm/contact';
|
||||||
import { getCustomerSimpleList } from '#/api/crm/customer';
|
import { getCustomerSimpleList } from '#/api/crm/customer';
|
||||||
import { floatToFixed2 } from '#/utils';
|
import { getSimpleUserList } from '#/api/system/user';
|
||||||
|
import { erpPriceMultiply, floatToFixed2 } from '#/utils';
|
||||||
import { DICT_TYPE } from '#/utils/dict';
|
import { DICT_TYPE } from '#/utils/dict';
|
||||||
|
|
||||||
/** 新增/修改的表单 */
|
/** 新增/修改的表单 */
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
export function useFormSchema(): VbenFormSchema[] {
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
fieldName: 'id',
|
||||||
|
component: 'Input',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: [''],
|
||||||
|
show: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'no',
|
fieldName: 'no',
|
||||||
label: '合同编号',
|
label: '合同编号',
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请输入合同编号',
|
placeholder: '保存时自动生成',
|
||||||
|
disabled: () => true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -28,9 +38,22 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
placeholder: '请输入合同名称',
|
placeholder: '请输入合同名称',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'ownerUserId',
|
||||||
|
label: '负责人',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
api: () => getSimpleUserList(),
|
||||||
|
fieldNames: {
|
||||||
|
label: 'nickname',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: 'required',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'customerId',
|
fieldName: 'customerId',
|
||||||
label: '客户',
|
label: '客户名称',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
@ -42,9 +65,8 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'businessId',
|
fieldName: 'businessId',
|
||||||
label: '商机',
|
label: '商机名称',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleBusinessList,
|
api: getSimpleBusinessList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
|
@ -52,49 +74,53 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
placeholder: '请选择商机',
|
placeholder: '请选择商机',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldName: 'totalPrice',
|
|
||||||
label: '合同金额',
|
|
||||||
component: 'InputNumber',
|
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入合同金额',
|
|
||||||
min: 0,
|
|
||||||
precision: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldName: 'orderDate',
|
fieldName: 'orderDate',
|
||||||
label: '下单时间',
|
label: '下单日期',
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
rules: 'required',
|
rules: 'required',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择下单时间',
|
showTime: false,
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'x',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'startTime',
|
fieldName: 'startTime',
|
||||||
label: '合同开始时间',
|
label: '合同开始时间',
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择合同开始时间',
|
showTime: false,
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'x',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'endTime',
|
fieldName: 'endTime',
|
||||||
label: '合同结束时间',
|
label: '合同结束时间',
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: '请选择合同结束时间',
|
showTime: false,
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
valueFormat: 'x',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'signUserId',
|
||||||
|
label: '公司签约人',
|
||||||
|
component: 'ApiSelect',
|
||||||
|
componentProps: {
|
||||||
|
api: () => getSimpleUserList(),
|
||||||
|
fieldNames: {
|
||||||
|
label: 'nickname',
|
||||||
|
value: 'id',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldName: 'signContactId',
|
fieldName: 'signContactId',
|
||||||
label: '客户签约人',
|
label: '客户签约人',
|
||||||
component: 'ApiSelect',
|
component: 'ApiSelect',
|
||||||
rules: 'required',
|
|
||||||
componentProps: {
|
componentProps: {
|
||||||
api: getSimpleContactList,
|
api: getSimpleContactList,
|
||||||
labelField: 'name',
|
labelField: 'name',
|
||||||
|
@ -111,6 +137,50 @@ export function useFormSchema(): VbenFormSchema[] {
|
||||||
rows: 4,
|
rows: 4,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'product',
|
||||||
|
label: '产品清单',
|
||||||
|
component: 'Input',
|
||||||
|
formItemClass: 'col-span-3',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'totalProductPrice',
|
||||||
|
label: '产品总金额',
|
||||||
|
component: 'InputNumber',
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'discountPercent',
|
||||||
|
label: '整单折扣(%)',
|
||||||
|
component: 'InputNumber',
|
||||||
|
rules: z.number().min(0).max(100).default(0),
|
||||||
|
componentProps: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldName: 'totalPrice',
|
||||||
|
label: '折扣后金额',
|
||||||
|
component: 'InputNumber',
|
||||||
|
dependencies: {
|
||||||
|
triggerFields: ['totalProductPrice', 'discountPercent'],
|
||||||
|
disabled: () => true,
|
||||||
|
trigger(values, form) {
|
||||||
|
const discountPrice =
|
||||||
|
erpPriceMultiply(
|
||||||
|
values.totalProductPrice,
|
||||||
|
values.discountPercent / 100,
|
||||||
|
) ?? 0;
|
||||||
|
form.setFieldValue(
|
||||||
|
'totalPrice',
|
||||||
|
values.totalProductPrice - discountPrice,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,10 @@ import {
|
||||||
getContract,
|
getContract,
|
||||||
updateContract,
|
updateContract,
|
||||||
} from '#/api/crm/contract';
|
} from '#/api/crm/contract';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
import { erpPriceMultiply } from '#/utils';
|
||||||
|
import { ProductEditTable } from '#/views/crm/product';
|
||||||
|
|
||||||
import { useFormSchema } from '../data';
|
import { useFormSchema } from '../data';
|
||||||
|
|
||||||
|
@ -24,15 +27,37 @@ const getTitle = computed(() => {
|
||||||
: $t('ui.actionTitle.create', ['合同']);
|
: $t('ui.actionTitle.create', ['合同']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function handleUpdateProducts(products: any) {
|
||||||
|
formData.value = modalApi.getData<CrmContractApi.Contract>();
|
||||||
|
formData.value!.products = products;
|
||||||
|
if (formData.value) {
|
||||||
|
const totalProductPrice =
|
||||||
|
formData.value.products?.reduce(
|
||||||
|
(prev, curr) => prev + curr.totalPrice,
|
||||||
|
0,
|
||||||
|
) ?? 0;
|
||||||
|
const discountPercent = formData.value.discountPercent;
|
||||||
|
const discountPrice =
|
||||||
|
discountPercent === null
|
||||||
|
? 0
|
||||||
|
: erpPriceMultiply(totalProductPrice, discountPercent / 100);
|
||||||
|
const totalPrice = totalProductPrice - (discountPrice ?? 0);
|
||||||
|
formData.value!.totalProductPrice = totalProductPrice;
|
||||||
|
formData.value!.totalPrice = totalPrice;
|
||||||
|
formApi.setValues(formData.value!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
const [Form, formApi] = useVbenForm({
|
||||||
commonConfig: {
|
commonConfig: {
|
||||||
componentProps: {
|
componentProps: {
|
||||||
class: 'w-full',
|
class: 'w-full',
|
||||||
},
|
},
|
||||||
|
labelWidth: 120,
|
||||||
},
|
},
|
||||||
// 一共2列
|
// 一共3列
|
||||||
wrapperClass: 'grid-cols-2',
|
wrapperClass: 'grid-cols-3',
|
||||||
layout: 'horizontal',
|
layout: 'vertical',
|
||||||
schema: useFormSchema(),
|
schema: useFormSchema(),
|
||||||
showDefaultActions: false,
|
showDefaultActions: false,
|
||||||
});
|
});
|
||||||
|
@ -46,6 +71,7 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as CrmContractApi.Contract;
|
const data = (await formApi.getValues()) as CrmContractApi.Contract;
|
||||||
|
data.products = formData.value?.products;
|
||||||
try {
|
try {
|
||||||
await (formData.value?.id ? updateContract(data) : createContract(data));
|
await (formData.value?.id ? updateContract(data) : createContract(data));
|
||||||
// 关闭并提示
|
// 关闭并提示
|
||||||
|
@ -79,7 +105,17 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal :title="getTitle" class="w-[40%]">
|
<Modal :title="getTitle" class="w-[50%]">
|
||||||
<Form class="mx-4" />
|
<Form class="mx-4">
|
||||||
|
<template #product="slotProps">
|
||||||
|
<ProductEditTable
|
||||||
|
v-bind="slotProps"
|
||||||
|
class="w-full"
|
||||||
|
:products="formData?.products ?? []"
|
||||||
|
:biz-type="BizTypeEnum.CRM_CONTRACT"
|
||||||
|
@update:products="handleUpdateProducts"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -174,3 +174,60 @@ export function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 代码生成表格列定义 */
|
||||||
|
export function useProductEditTableColumns(): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{ type: 'seq', title: '序号', minWidth: 50 },
|
||||||
|
{
|
||||||
|
field: 'productId',
|
||||||
|
title: '产品名称',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'productId' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productNo',
|
||||||
|
title: '条码',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productUnit',
|
||||||
|
title: '单位',
|
||||||
|
minWidth: 100,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.CRM_PRODUCT_UNIT },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productPrice',
|
||||||
|
title: '价格(元)',
|
||||||
|
minWidth: 100,
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'sellingPrice',
|
||||||
|
title: '售价(元)',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'sellingPrice' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'count',
|
||||||
|
title: '数量',
|
||||||
|
minWidth: 100,
|
||||||
|
slots: { default: 'count' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
title: '合计',
|
||||||
|
minWidth: 100,
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
width: 80,
|
||||||
|
fixed: 'right',
|
||||||
|
slots: { default: 'actions' },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -15,3 +15,7 @@ export const ProductDetails = defineAsyncComponent(
|
||||||
export const ProductDetailsList = defineAsyncComponent(
|
export const ProductDetailsList = defineAsyncComponent(
|
||||||
() => import('./modules/detail-list.vue'),
|
() => import('./modules/detail-list.vue'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const ProductEditTable = defineAsyncComponent(
|
||||||
|
() => import('./modules/product-table.vue'),
|
||||||
|
);
|
||||||
|
|
|
@ -0,0 +1,183 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { CrmBusinessApi } from '#/api/crm/business';
|
||||||
|
import type { CrmContractApi } from '#/api/crm/contract';
|
||||||
|
import type { CrmProductApi } from '#/api/crm/product';
|
||||||
|
|
||||||
|
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { InputNumber, Select } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
|
import { getProductSimpleList } from '#/api/crm/product';
|
||||||
|
import { erpPriceMultiply } from '#/utils';
|
||||||
|
|
||||||
|
import { useProductEditTableColumns } from '../data';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
bizType: BizTypeEnum;
|
||||||
|
products?:
|
||||||
|
| CrmBusinessApi.BusinessProduct[]
|
||||||
|
| CrmContractApi.ContractProduct[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:products']);
|
||||||
|
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
|
||||||
|
function handleAdd() {
|
||||||
|
gridApi.grid.insertAt(null, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDelete(row: CrmProductApi.Product) {
|
||||||
|
gridApi.grid.remove(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleProductChange(productId: any, row: any) {
|
||||||
|
const product = productOptions.value.find((p) => p.id === productId);
|
||||||
|
if (!product) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row.productUnit = product.unit;
|
||||||
|
row.productNo = product.no;
|
||||||
|
row.productPrice = product.price;
|
||||||
|
row.sellingPrice = product.price;
|
||||||
|
row.count = 0;
|
||||||
|
row.totalPrice = 0;
|
||||||
|
handleUpdateValue(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePriceChange(row: any) {
|
||||||
|
row.totalPrice = erpPriceMultiply(row.sellingPrice, row.count) ?? 0;
|
||||||
|
handleUpdateValue(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleUpdateValue(row: any) {
|
||||||
|
const index = tableData.value.findIndex((item) => item.id === row.id);
|
||||||
|
if (props.bizType === BizTypeEnum.CRM_BUSINESS) {
|
||||||
|
row.businessPrice = row.sellingPrice;
|
||||||
|
} else if (props.bizType === BizTypeEnum.CRM_CONTRACT) {
|
||||||
|
row.contractPrice = row.sellingPrice;
|
||||||
|
}
|
||||||
|
if (index === -1) {
|
||||||
|
row.id = tableData.value.length + 1;
|
||||||
|
tableData.value.push(row);
|
||||||
|
} else {
|
||||||
|
tableData.value[index] = row;
|
||||||
|
}
|
||||||
|
emit('update:products', tableData.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 表格配置 */
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
editConfig: {
|
||||||
|
trigger: 'click',
|
||||||
|
mode: 'cell',
|
||||||
|
},
|
||||||
|
columns: useProductEditTableColumns(),
|
||||||
|
data: tableData.value,
|
||||||
|
border: true,
|
||||||
|
showOverflow: true,
|
||||||
|
autoResize: true,
|
||||||
|
keepSource: true,
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 监听外部传入的列数据 */
|
||||||
|
watch(
|
||||||
|
() => props.products,
|
||||||
|
async (products) => {
|
||||||
|
if (!products) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await nextTick();
|
||||||
|
tableData.value = products;
|
||||||
|
if (props.bizType === BizTypeEnum.CRM_BUSINESS) {
|
||||||
|
tableData.value.forEach((item) => {
|
||||||
|
item.sellingPrice = item.businessPrice;
|
||||||
|
});
|
||||||
|
} else if (props.bizType === BizTypeEnum.CRM_CONTRACT) {
|
||||||
|
tableData.value.forEach((item) => {
|
||||||
|
item.sellingPrice = item.contractPrice;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
gridApi.grid?.loadData(tableData.value);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 初始化 */
|
||||||
|
const productOptions = ref<CrmProductApi.Product[]>([]);
|
||||||
|
onMounted(async () => {
|
||||||
|
productOptions.value = await getProductSimpleList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Grid class="w-full">
|
||||||
|
<template #productId="{ row }">
|
||||||
|
<Select
|
||||||
|
v-model:value="row.productId"
|
||||||
|
:options="productOptions"
|
||||||
|
:field-names="{ label: 'name', value: 'id' }"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleProductChange($event, row)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #sellingPrice="{ row }">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="row.sellingPrice"
|
||||||
|
:min="0.001"
|
||||||
|
:precision="2"
|
||||||
|
@change="handlePriceChange(row)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #count="{ row }">
|
||||||
|
<InputNumber
|
||||||
|
v-model:value="row.count"
|
||||||
|
:min="0.001"
|
||||||
|
:precision="3"
|
||||||
|
@change="handlePriceChange(row)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bottom>
|
||||||
|
<TableAction
|
||||||
|
class="mt-4 flex justify-center"
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: '添加产品',
|
||||||
|
type: 'default',
|
||||||
|
onClick: handleAdd,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #actions="{ row }">
|
||||||
|
<TableAction
|
||||||
|
:actions="[
|
||||||
|
{
|
||||||
|
label: $t('common.delete'),
|
||||||
|
type: 'link',
|
||||||
|
danger: true,
|
||||||
|
popConfirm: {
|
||||||
|
title: $t('ui.actionMessage.deleteConfirm', [row.name]),
|
||||||
|
confirm: handleDelete.bind(null, row),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
</template>
|
Loading…
Reference in New Issue