feat: crm detail
							parent
							
								
									b705a81eb0
								
							
						
					
					
						commit
						91a9c508a0
					
				|  | @ -34,10 +34,21 @@ export namespace CrmReceivableApi { | |||
|     createTime: Date; // 创建时间
 | ||||
|     updateTime: Date; // 更新时间
 | ||||
|   } | ||||
| 
 | ||||
|   export interface ReceivablePageParam extends PageParam { | ||||
|     no?: string; | ||||
|     planId?: number; | ||||
|     customerId?: number; | ||||
|     contractId?: number; | ||||
|     sceneType?: number; | ||||
|     auditStatus?: number; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 查询回款列表 */ | ||||
| export function getReceivablePage(params: PageParam) { | ||||
| export function getReceivablePage( | ||||
|   params: CrmReceivableApi.ReceivablePageParam, | ||||
| ) { | ||||
|   return requestClient.get<PageResult<CrmReceivableApi.Receivable>>( | ||||
|     '/crm/receivable/page', | ||||
|     { params }, | ||||
|  | @ -45,7 +56,9 @@ export function getReceivablePage(params: PageParam) { | |||
| } | ||||
| 
 | ||||
| /** 查询回款列表,基于指定客户 */ | ||||
| export function getReceivablePageByCustomer(params: PageParam) { | ||||
| export function getReceivablePageByCustomer( | ||||
|   params: CrmReceivableApi.ReceivablePageParam, | ||||
| ) { | ||||
|   return requestClient.get<PageResult<CrmReceivableApi.Receivable>>( | ||||
|     '/crm/receivable/page-by-customer', | ||||
|     { params }, | ||||
|  |  | |||
|  | @ -21,8 +21,6 @@ import CustomerTodayContactList from './modules/customer-today-contact-list.vue' | |||
| import ReceivableAuditList from './modules/receivable-audit-list.vue'; | ||||
| import ReceivablePlanRemindList from './modules/receivable-plan-remind-list.vue'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmBacklog' }); | ||||
| 
 | ||||
| const leftMenu = ref('customerTodayContact'); | ||||
| 
 | ||||
| const clueFollowCount = ref(0); | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmCustomerDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   business: CrmBusinessApi.Business; // 商机信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmClueDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   clue: CrmClueApi.Clue; // 线索信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmContactDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   contact: CrmContactApi.Contact; // 联系人信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmContractDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   contract: CrmContractApi.Contract; // 合同信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmCustomerDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   customer: CrmCustomerApi.Customer; // 客户信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -21,8 +21,6 @@ import { $t } from '#/locales'; | |||
| import { useGridColumns } from './data'; | ||||
| import Form from './permission-form.vue'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmPermissionList' }); | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   bizId: number; // 模块数据编号 | ||||
|   bizType: number; // 模块类型 | ||||
|  |  | |||
|  | @ -18,8 +18,6 @@ import { $t } from '#/locales'; | |||
| 
 | ||||
| import { useTransferFormSchema } from './data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmTransferForm' }); | ||||
| 
 | ||||
| const emit = defineEmits(['success']); | ||||
| 
 | ||||
| const bizType = defineModel<number>('bizType'); | ||||
|  |  | |||
|  | @ -5,8 +5,6 @@ import { useDescription } from '#/components/description'; | |||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineOptions({ name: 'CrmProductDetailsInfo' }); | ||||
| 
 | ||||
| defineProps<{ | ||||
|   product: CrmProductApi.Product; // 产品信息 | ||||
| }>(); | ||||
|  |  | |||
|  | @ -1,10 +1,17 @@ | |||
| import type { VbenFormSchema } from '#/adapter/form'; | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { DescriptionItemSchema } from '#/components/description'; | ||||
| 
 | ||||
| import { h } from 'vue'; | ||||
| 
 | ||||
| import { formatDateTime } from '@vben/utils'; | ||||
| 
 | ||||
| import { getContractSimpleList } from '#/api/crm/contract'; | ||||
| import { getCustomerSimpleList } from '#/api/crm/customer'; | ||||
| import { getReceivablePlanSimpleList } from '#/api/crm/receivable/plan'; | ||||
| import { getSimpleUserList } from '#/api/system/user'; | ||||
| import { DictTag } from '#/components/dict-tag'; | ||||
| import { erpPriceInputFormatter } from '#/utils'; | ||||
| import { DICT_TYPE, getDictOptions } from '#/utils/dict'; | ||||
| 
 | ||||
| /** 新增/修改的表单 */ | ||||
|  | @ -267,3 +274,150 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { | |||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 详情页的字段 */ | ||||
| export function useDetailSchema(): DescriptionItemSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       field: 'customerName', | ||||
|       label: '客户名称', | ||||
|     }, | ||||
|     { | ||||
|       field: 'totalPrice', | ||||
|       label: '合同金额', | ||||
|       content: (data) => erpPriceInputFormatter(data.totalPrice), | ||||
|     }, | ||||
|     { | ||||
|       field: 'returnTime', | ||||
|       label: '回款日期', | ||||
|       content: (data) => formatDateTime(data?.returnTime) as string, | ||||
|     }, | ||||
|     { | ||||
|       field: 'price', | ||||
|       label: '回款金额', | ||||
|       content: (data) => erpPriceInputFormatter(data.price), | ||||
|     }, | ||||
|     { | ||||
|       field: 'ownerUserName', | ||||
|       label: '负责人', | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 详情页的基础字段 */ | ||||
| export function useDetailBaseSchema(): DescriptionItemSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       field: 'no', | ||||
|       label: '回款编号', | ||||
|     }, | ||||
|     { | ||||
|       field: 'customerName', | ||||
|       label: '客户名称', | ||||
|     }, | ||||
|     { | ||||
|       field: 'contract', | ||||
|       label: '合同编号', | ||||
|       content: (data) => data?.contract?.no, | ||||
|     }, | ||||
|     { | ||||
|       field: 'returnTime', | ||||
|       label: '回款日期', | ||||
|       content: (data) => formatDateTime(data?.returnTime) as string, | ||||
|     }, | ||||
|     { | ||||
|       field: 'price', | ||||
|       label: '回款金额', | ||||
|       content: (data) => erpPriceInputFormatter(data.price), | ||||
|     }, | ||||
|     { | ||||
|       field: 'returnType', | ||||
|       label: '回款方式', | ||||
|       content: (data) => | ||||
|         h(DictTag, { | ||||
|           type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE, | ||||
|           value: data?.returnType, | ||||
|         }), | ||||
|     }, | ||||
|     { | ||||
|       field: 'remark', | ||||
|       label: '备注', | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 详情列表的字段 */ | ||||
| export function useDetailListColumns(): VxeTableGridOptions['columns'] { | ||||
|   return [ | ||||
|     { | ||||
|       title: '回款编号', | ||||
|       field: 'no', | ||||
|       minWidth: 150, | ||||
|       fixed: 'left', | ||||
|     }, | ||||
|     { | ||||
|       title: '客户名称', | ||||
|       field: 'customerName', | ||||
|       minWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|       title: '合同编号', | ||||
|       field: 'contract', | ||||
|       minWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|       title: '回款日期', | ||||
|       field: 'returnTime', | ||||
|       minWidth: 150, | ||||
|       formatter: 'formatDateTime', | ||||
|     }, | ||||
|     { | ||||
|       title: '回款金额(元)', | ||||
|       field: 'price', | ||||
|       minWidth: 150, | ||||
|       formatter: 'formatNumber', | ||||
|     }, | ||||
|     { | ||||
|       title: '回款方式', | ||||
|       field: 'returnType', | ||||
|       minWidth: 150, | ||||
|       cellRender: { | ||||
|         name: 'CellDict', | ||||
|         props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       title: '负责人', | ||||
|       field: 'ownerUserName', | ||||
|       minWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|       title: '备注', | ||||
|       field: 'remark', | ||||
|       minWidth: 150, | ||||
|     }, | ||||
|     { | ||||
|       title: '合同金额(元)', | ||||
|       field: 'contract.totalPrice', | ||||
|       minWidth: 150, | ||||
|       formatter: 'formatNumber', | ||||
|     }, | ||||
|     { | ||||
|       title: '回款状态', | ||||
|       field: 'auditStatus', | ||||
|       minWidth: 100, | ||||
|       fixed: 'right', | ||||
|       cellRender: { | ||||
|         name: 'CellDict', | ||||
|         props: { type: DICT_TYPE.CRM_AUDIT_STATUS }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       title: '操作', | ||||
|       field: 'actions', | ||||
|       width: 130, | ||||
|       fixed: 'right', | ||||
|       slots: { default: 'actions' }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,42 @@ | |||
| <script lang="ts" setup></script> | ||||
| <script lang="ts" setup> | ||||
| import type { CrmReceivableApi } from '#/api/crm/receivable'; | ||||
| 
 | ||||
| import { Divider } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { useDescription } from '#/components/description'; | ||||
| import { useFollowUpDetailSchema } from '#/views/crm/followup/data'; | ||||
| 
 | ||||
| import { useDetailBaseSchema } from '../data'; | ||||
| 
 | ||||
| defineProps<{ | ||||
|   receivable: CrmReceivableApi.Receivable; // 收款信息 | ||||
| }>(); | ||||
| 
 | ||||
| const [BaseDescription] = useDescription({ | ||||
|   componentProps: { | ||||
|     title: '基本信息', | ||||
|     bordered: false, | ||||
|     column: 4, | ||||
|     class: 'mx-4', | ||||
|   }, | ||||
|   schema: useDetailBaseSchema(), | ||||
| }); | ||||
| 
 | ||||
| const [SystemDescription] = useDescription({ | ||||
|   componentProps: { | ||||
|     title: '系统信息', | ||||
|     bordered: false, | ||||
|     column: 3, | ||||
|     class: 'mx-4', | ||||
|   }, | ||||
|   schema: useFollowUpDetailSchema(), | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div>receivableInfo</div> | ||||
|   <div class="p-4"> | ||||
|     <BaseDescription :data="receivable" /> | ||||
|     <Divider /> | ||||
|     <SystemDescription :data="receivable" /> | ||||
|   </div> | ||||
| </template> | ||||
|  |  | |||
|  | @ -1,4 +1,157 @@ | |||
| <script lang="ts" setup></script> | ||||
| <script lang="ts" setup> | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { CrmBusinessApi } from '#/api/crm/business'; | ||||
| import type { CrmReceivableApi } from '#/api/crm/receivable'; | ||||
| 
 | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { useVbenModal } from '@vben/common-ui'; | ||||
| 
 | ||||
| import { message } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||
| import { | ||||
|   deleteReceivable, | ||||
|   getReceivablePageByCustomer, | ||||
| } from '#/api/crm/receivable'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useDetailListColumns } from '../data'; | ||||
| import Form from './form.vue'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   contractId?: number; // 合同编号 | ||||
|   customerId?: number; // 客户编号 | ||||
| }>(); | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: Form, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| const checkedRows = ref<CrmReceivableApi.Receivable[]>([]); | ||||
| function setCheckedRows({ | ||||
|   records, | ||||
| }: { | ||||
|   records: CrmReceivableApi.Receivable[]; | ||||
| }) { | ||||
|   checkedRows.value = records; | ||||
| } | ||||
| 
 | ||||
| /** 刷新表格 */ | ||||
| function onRefresh() { | ||||
|   gridApi.query(); | ||||
| } | ||||
| 
 | ||||
| /** 创建回款 */ | ||||
| function handleCreate() { | ||||
|   formModalApi.setData(null).open(); | ||||
| } | ||||
| 
 | ||||
| /** 编辑回款 */ | ||||
| function handleEdit(row: CrmReceivableApi.Receivable) { | ||||
|   formModalApi.setData({ receivable: row }).open(); | ||||
| } | ||||
| 
 | ||||
| /** 删除回款 */ | ||||
| async function handleDelete(row: CrmReceivableApi.Receivable) { | ||||
|   const hideLoading = message.loading({ | ||||
|     content: $t('ui.actionMessage.deleting', [row.no]), | ||||
|     key: 'action_key_msg', | ||||
|   }); | ||||
|   try { | ||||
|     await deleteReceivable(row.id as number); | ||||
|     message.success({ | ||||
|       content: $t('ui.actionMessage.deleteSuccess', [row.no]), | ||||
|       key: 'action_key_msg', | ||||
|     }); | ||||
|     onRefresh(); | ||||
|   } finally { | ||||
|     hideLoading(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const [Grid, gridApi] = useVbenVxeGrid({ | ||||
|   gridOptions: { | ||||
|     columns: useDetailListColumns(), | ||||
|     height: 600, | ||||
|     keepSource: true, | ||||
|     proxyConfig: { | ||||
|       ajax: { | ||||
|         query: async ({ page }, formValues) => { | ||||
|           const queryParams: CrmReceivableApi.ReceivablePageParam = { | ||||
|             page: page.currentPage, | ||||
|             pageSize: page.pageSize, | ||||
|             ...formValues, | ||||
|           }; | ||||
|           if (props.customerId && !props.contractId) { | ||||
|             queryParams.customerId = props.customerId; | ||||
|           } else if (props.customerId && props.contractId) { | ||||
|             // 如果是合同的话客户编号也需要带上因为权限基于客户 | ||||
|             queryParams.customerId = props.customerId; | ||||
|             queryParams.contractId = props.contractId; | ||||
|           } | ||||
|           return await getReceivablePageByCustomer(queryParams); | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     rowConfig: { | ||||
|       keyField: 'id', | ||||
|     }, | ||||
|     toolbarConfig: { | ||||
|       refresh: { code: 'query' }, | ||||
|       search: true, | ||||
|     }, | ||||
|   } as VxeTableGridOptions<CrmBusinessApi.Business>, | ||||
|   gridEvents: { | ||||
|     checkboxAll: setCheckedRows, | ||||
|     checkboxChange: setCheckedRows, | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div>receivableList</div> | ||||
|   <div> | ||||
|     <FormModal @success="onRefresh" /> | ||||
|     <Grid> | ||||
|       <template #toolbar-tools> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: $t('ui.actionTitle.create', ['回款']), | ||||
|               type: 'primary', | ||||
|               icon: ACTION_ICON.ADD, | ||||
|               auth: ['crm:business:create'], | ||||
|               onClick: handleCreate, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
|       <template #actions="{ row }"> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: $t('common.edit'), | ||||
|               type: 'link', | ||||
|               icon: ACTION_ICON.EDIT, | ||||
|               auth: ['crm:receivable:update'], | ||||
|               onClick: handleEdit.bind(null, row), | ||||
|               ifShow: row.auditStatus === 0, | ||||
|             }, | ||||
|             { | ||||
|               label: $t('common.delete'), | ||||
|               type: 'link', | ||||
|               danger: true, | ||||
|               icon: ACTION_ICON.DELETE, | ||||
|               auth: ['crm:receivable:delete'], | ||||
|               popConfirm: { | ||||
|                 title: $t('ui.actionMessage.deleteConfirm', [row.no]), | ||||
|                 confirm: handleDelete.bind(null, row), | ||||
|               }, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
|     </Grid> | ||||
|   </div> | ||||
| </template> | ||||
|  |  | |||
|  | @ -1,7 +1,139 @@ | |||
| <script lang="ts" setup></script> | ||||
| <script setup lang="ts"> | ||||
| import type { CrmReceivableApi } from '#/api/crm/receivable'; | ||||
| import type { SystemOperateLogApi } from '#/api/system/operate-log'; | ||||
| 
 | ||||
| import { computed, defineAsyncComponent, onMounted, ref } from 'vue'; | ||||
| import { useRoute, useRouter } from 'vue-router'; | ||||
| 
 | ||||
| import { Page, useVbenModal } from '@vben/common-ui'; | ||||
| import { useTabs } from '@vben/hooks'; | ||||
| import { ArrowLeft } from '@vben/icons'; | ||||
| 
 | ||||
| import { Button, Card, Tabs } from 'ant-design-vue'; | ||||
| 
 | ||||
| import { getOperateLogPage } from '#/api/crm/operateLog'; | ||||
| import { BizTypeEnum } from '#/api/crm/permission'; | ||||
| import { getReceivable } from '#/api/crm/receivable'; | ||||
| import { useDescription } from '#/components/description'; | ||||
| 
 | ||||
| import { useDetailSchema } from '../data'; | ||||
| import ReceivableForm from './form.vue'; | ||||
| 
 | ||||
| const PermissionList = defineAsyncComponent( | ||||
|   () => import('#/views/crm/permission/modules/permission-list.vue'), | ||||
| ); | ||||
| 
 | ||||
| const OperateLog = defineAsyncComponent( | ||||
|   () => import('#/components/operate-log'), | ||||
| ); | ||||
| 
 | ||||
| const ReceivableDetailsInfo = defineAsyncComponent( | ||||
|   () => import('./detail-info.vue'), | ||||
| ); | ||||
| 
 | ||||
| const loading = ref(false); | ||||
| 
 | ||||
| const route = useRoute(); | ||||
| const router = useRouter(); | ||||
| const tabs = useTabs(); | ||||
| 
 | ||||
| const receivableId = ref(0); | ||||
| 
 | ||||
| const receivable = ref<CrmReceivableApi.Receivable>( | ||||
|   {} as CrmReceivableApi.Receivable, | ||||
| ); | ||||
| const receivableLogList = ref<SystemOperateLogApi.OperateLog[]>([]); | ||||
| const permissionListRef = ref<InstanceType<typeof PermissionList>>(); // 团队成员列表 Ref | ||||
| 
 | ||||
| // 校验编辑权限 | ||||
| const validateWrite = computed(() => permissionListRef.value?.validateWrite); | ||||
| 
 | ||||
| const [Description] = useDescription({ | ||||
|   componentProps: { | ||||
|     bordered: false, | ||||
|     column: 4, | ||||
|     class: 'mx-4', | ||||
|   }, | ||||
|   schema: useDetailSchema(), | ||||
| }); | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: ReceivableForm, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| /** 加载线索详情 */ | ||||
| async function loadReceivableDetail() { | ||||
|   loading.value = true; | ||||
|   const data = await getReceivable(receivableId.value); | ||||
|   receivable.value = data; | ||||
|   // 操作日志 | ||||
|   const logList = await getOperateLogPage({ | ||||
|     bizType: BizTypeEnum.CRM_RECEIVABLE, | ||||
|     bizId: receivableId.value, | ||||
|   }); | ||||
|   receivableLogList.value = logList.list; | ||||
|   loading.value = false; | ||||
| } | ||||
| 
 | ||||
| /** 返回列表页 */ | ||||
| function handleBack() { | ||||
|   tabs.closeCurrentTab(); | ||||
|   router.push('/crm/receivable'); | ||||
| } | ||||
| 
 | ||||
| /** 编辑收款 */ | ||||
| function handleEdit() { | ||||
|   formModalApi.setData({ id: receivableId.value }).open(); | ||||
| } | ||||
| 
 | ||||
| // 加载数据 | ||||
| onMounted(async () => { | ||||
|   receivableId.value = Number(route.params.id); | ||||
|   await loadReceivableDetail(); | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <div> | ||||
|     <p>待完成</p> | ||||
|   <Page auto-content-height :title="receivable?.no" :loading="loading"> | ||||
|     <FormModal @success="loadReceivableDetail" /> | ||||
|     <template #extra> | ||||
|       <div class="flex items-center gap-2"> | ||||
|         <Button @click="handleBack"> | ||||
|           <ArrowLeft class="size-5" /> | ||||
|           返回 | ||||
|         </Button> | ||||
|         <Button | ||||
|           v-if="validateWrite" | ||||
|           type="primary" | ||||
|           @click="handleEdit" | ||||
|           v-access:code="['crm:receivable:update']" | ||||
|         > | ||||
|           {{ $t('ui.actionTitle.edit') }} | ||||
|         </Button> | ||||
|       </div> | ||||
|     </template> | ||||
|     <Card class="min-h-[10%]"> | ||||
|       <Description :data="receivable" /> | ||||
|     </Card> | ||||
|     <Card class="mt-4 min-h-[60%]"> | ||||
|       <Tabs> | ||||
|         <Tabs.TabPane tab="详细资料" key="1" :force-render="true"> | ||||
|           <ReceivableDetailsInfo :receivable="receivable" /> | ||||
|         </Tabs.TabPane> | ||||
|         <Tabs.TabPane tab="团队成员" key="2" :force-render="true"> | ||||
|           <PermissionList | ||||
|             ref="permissionListRef" | ||||
|             :biz-id="receivableId" | ||||
|             :biz-type="BizTypeEnum.CRM_RECEIVABLE" | ||||
|             :show-action="true" | ||||
|             @quit-team="handleBack" | ||||
|           /> | ||||
|         </Tabs.TabPane> | ||||
|         <Tabs.TabPane tab="操作日志" key="3" :force-render="true"> | ||||
|           <OperateLog :log-list="receivableLogList" /> | ||||
|         </Tabs.TabPane> | ||||
|       </Tabs> | ||||
|     </Card> | ||||
|   </Page> | ||||
| </template> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 xingyu4j
						xingyu4j