feat: crm detail
parent
181367791f
commit
d576f7b18a
|
@ -33,6 +33,10 @@ const FollowUp = defineAsyncComponent(
|
||||||
() => import('#/views/crm/followup/index.vue'),
|
() => import('#/views/crm/followup/index.vue'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ProductDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/product/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
const PermissionList = defineAsyncComponent(
|
const PermissionList = defineAsyncComponent(
|
||||||
() => import('#/views/crm/permission/modules/permission-list.vue'),
|
() => import('#/views/crm/permission/modules/permission-list.vue'),
|
||||||
);
|
);
|
||||||
|
@ -124,9 +128,9 @@ async function handleUpdateStatus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
businessId.value = Number(route.params.id);
|
businessId.value = Number(route.params.id);
|
||||||
await loadBusinessDetail();
|
loadBusinessDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -173,12 +177,15 @@ onMounted(async () => {
|
||||||
<ContactDetailsList
|
<ContactDetailsList
|
||||||
:biz-id="businessId"
|
:biz-id="businessId"
|
||||||
:biz-type="BizTypeEnum.CRM_BUSINESS"
|
:biz-type="BizTypeEnum.CRM_BUSINESS"
|
||||||
:business-id="business.id"
|
:business-id="businessId"
|
||||||
:customer-id="business.customerId"
|
:customer-id="business.customerId"
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="产品" key="4" :force-render="true">
|
<Tabs.TabPane tab="产品" key="4" :force-render="true">
|
||||||
<div>产品</div>
|
<ProductDetailsList
|
||||||
|
:biz-type="BizTypeEnum.CRM_BUSINESS"
|
||||||
|
:business="business"
|
||||||
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="合同" key="5" :force-render="true">
|
<Tabs.TabPane tab="合同" key="5" :force-render="true">
|
||||||
<ContractDetailsList
|
<ContractDetailsList
|
||||||
|
|
|
@ -127,9 +127,9 @@ async function handleTransform(): Promise<boolean | undefined> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
clueId.value = Number(route.params.id);
|
clueId.value = Number(route.params.id);
|
||||||
await loadClueDetail();
|
loadClueDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -107,9 +107,9 @@ function handleTransfer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
contactId.value = Number(route.params.id);
|
contactId.value = Number(route.params.id);
|
||||||
await loadContactDetail();
|
loadContactDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ const FollowUp = defineAsyncComponent(
|
||||||
() => import('#/views/crm/followup/index.vue'),
|
() => import('#/views/crm/followup/index.vue'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ProductDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/product/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
const PermissionList = defineAsyncComponent(
|
const PermissionList = defineAsyncComponent(
|
||||||
() => import('#/views/crm/permission/modules/permission-list.vue'),
|
() => import('#/views/crm/permission/modules/permission-list.vue'),
|
||||||
);
|
);
|
||||||
|
@ -39,6 +43,14 @@ const ContractDetailsInfo = defineAsyncComponent(
|
||||||
() => import('./detail-info.vue'),
|
() => import('./detail-info.vue'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ReceivableDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/receivable/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ReceivablePlanDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/receivable/plan/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -107,9 +119,9 @@ function handleTransfer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
contractId.value = Number(route.params.id);
|
contractId.value = Number(route.params.id);
|
||||||
await loadContractDetail();
|
loadContractDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -147,8 +159,22 @@ onMounted(async () => {
|
||||||
<Tabs.TabPane tab="合同跟进" key="2" :force-render="true">
|
<Tabs.TabPane tab="合同跟进" key="2" :force-render="true">
|
||||||
<FollowUp :biz-id="contractId" :biz-type="BizTypeEnum.CRM_CONTRACT" />
|
<FollowUp :biz-id="contractId" :biz-type="BizTypeEnum.CRM_CONTRACT" />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="产品" key="3" :force-render="true" />
|
<Tabs.TabPane tab="产品" key="3" :force-render="true">
|
||||||
<Tabs.TabPane tab="回款" key="4" :force-render="true" />
|
<ProductDetailsList
|
||||||
|
:biz-type="BizTypeEnum.CRM_CONTRACT"
|
||||||
|
:contract="contract"
|
||||||
|
/>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="回款" key="4" :force-render="true">
|
||||||
|
<ReceivablePlanDetailsList
|
||||||
|
:contract-id="contractId"
|
||||||
|
:customer-id="contract.customerId"
|
||||||
|
/>
|
||||||
|
<ReceivableDetailsList
|
||||||
|
:contract-id="contractId"
|
||||||
|
:customer-id="contract.customerId"
|
||||||
|
/>
|
||||||
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="团队成员" key="5" :force-render="true">
|
<Tabs.TabPane tab="团队成员" key="5" :force-render="true">
|
||||||
<PermissionList
|
<PermissionList
|
||||||
ref="permissionListRef"
|
ref="permissionListRef"
|
||||||
|
|
|
@ -57,6 +57,14 @@ const OperateLog = defineAsyncComponent(
|
||||||
() => import('#/components/operate-log'),
|
() => import('#/components/operate-log'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ReceivableDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/receivable/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const ReceivablePlanDetailsList = defineAsyncComponent(
|
||||||
|
() => import('#/views/crm/receivable/plan/modules/detail-list.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -174,9 +182,9 @@ async function handleUpdateDealStatus(): Promise<boolean | undefined> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
customerId.value = Number(route.params.id);
|
customerId.value = Number(route.params.id);
|
||||||
await loadCustomerDetail();
|
loadCustomerDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -283,7 +291,8 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="回款" key="7" :force-render="true">
|
<Tabs.TabPane tab="回款" key="7" :force-render="true">
|
||||||
<div>回款</div>
|
<ReceivablePlanDetailsList :customer-id="customerId" />
|
||||||
|
<ReceivableDetailsList :customer-id="customerId" />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="操作日志" key="8" :force-render="true">
|
<Tabs.TabPane tab="操作日志" key="8" :force-render="true">
|
||||||
<OperateLog :log-list="customerLogList" />
|
<OperateLog :log-list="customerLogList" />
|
||||||
|
|
|
@ -247,3 +247,48 @@ export function useDetailBaseSchema(): DescriptionItemSchema[] {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 详情列表的字段 */
|
||||||
|
export function useDetailListColumns(
|
||||||
|
showBussinePrice: boolean,
|
||||||
|
): VxeTableGridOptions['columns'] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
field: 'productName',
|
||||||
|
title: '产品名称',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productNo',
|
||||||
|
title: '产品条码',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productUnit',
|
||||||
|
title: '产品单位',
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.CRM_PRODUCT_UNIT },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'productPrice',
|
||||||
|
title: '产品价格(元)',
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'businessPrice',
|
||||||
|
title: '商机价格(元)',
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
visible: showBussinePrice,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'count',
|
||||||
|
title: '数量',
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'totalPrice',
|
||||||
|
title: '合计金额(元)',
|
||||||
|
formatter: 'formatNumber',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
|
||||||
|
import type { CrmBusinessApi } from '#/api/crm/business';
|
||||||
|
import type { CrmContractApi } from '#/api/crm/contract';
|
||||||
|
import type { CrmProductApi } from '#/api/crm/product';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
|
import { erpPriceInputFormatter } from '#/utils';
|
||||||
|
|
||||||
|
import { useDetailListColumns } from '../data';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
bizType: BizTypeEnum;
|
||||||
|
business?: CrmBusinessApi.Business; // 商机
|
||||||
|
contract?: CrmContractApi.Contract; // 合同
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const [Grid] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: useDetailListColumns(props.bizType === BizTypeEnum.CRM_BUSINESS),
|
||||||
|
data:
|
||||||
|
props.bizType === BizTypeEnum.CRM_BUSINESS
|
||||||
|
? props.business?.products
|
||||||
|
: props.contract?.products,
|
||||||
|
height: 600,
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
keepSource: true,
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<CrmProductApi.Product>,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Grid />
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<span class="font-bold text-red-500">
|
||||||
|
整单折扣:{{
|
||||||
|
erpPriceInputFormatter(
|
||||||
|
business ? business.discountPercent : contract?.discountPercent,
|
||||||
|
)
|
||||||
|
}}%
|
||||||
|
</span>
|
||||||
|
<span class="ml-4 font-bold text-red-500">
|
||||||
|
产品总金额:{{
|
||||||
|
erpPriceInputFormatter(
|
||||||
|
business ? business.totalProductPrice : contract?.totalProductPrice,
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
元
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -63,10 +63,11 @@ function handleBack() {
|
||||||
tabs.closeCurrentTab();
|
tabs.closeCurrentTab();
|
||||||
router.push('/crm/product');
|
router.push('/crm/product');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
productId.value = Number(route.params.id);
|
productId.value = Number(route.params.id);
|
||||||
await loadProductDetail();
|
loadProductDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,9 @@ function handleEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
receivableId.value = Number(route.params.id);
|
receivableId.value = Number(route.params.id);
|
||||||
await loadReceivableDetail();
|
loadReceivableDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,9 @@ function handleEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载数据
|
// 加载数据
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
receivablePlanId.value = Number(route.params.id);
|
receivablePlanId.value = Number(route.params.id);
|
||||||
await loadreceivablePlanDetail();
|
loadreceivablePlanDetail();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue