Merge remote-tracking branch 'yudao/dev' into dev
						commit
						a2832f1546
					
				| 
						 | 
					@ -12,16 +12,14 @@ export namespace CrmCustomerLimitConfigApi {
 | 
				
			||||||
    maxCount?: number;
 | 
					    maxCount?: number;
 | 
				
			||||||
    dealCountEnabled?: boolean;
 | 
					    dealCountEnabled?: boolean;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					/** 客户限制配置类型 */
 | 
				
			||||||
   * 客户限制配置类型
 | 
					export enum LimitConfType {
 | 
				
			||||||
   */
 | 
					  /** 锁定客户数限制 */
 | 
				
			||||||
  export enum LimitConfType {
 | 
					  CUSTOMER_LOCK_LIMIT = 2,
 | 
				
			||||||
    /** 锁定客户数限制 */
 | 
					  /** 拥有客户数限制 */
 | 
				
			||||||
    CUSTOMER_LOCK_LIMIT = 2,
 | 
					  CUSTOMER_QUANTITY_LIMIT = 1,
 | 
				
			||||||
    /** 拥有客户数限制 */
 | 
					 | 
				
			||||||
    CUSTOMER_QUANTITY_LIMIT = 1,
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 查询客户限制配置列表 */
 | 
					/** 查询客户限制配置列表 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,3 @@
 | 
				
			||||||
import type { PageParam } from '@vben/request';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { requestClient } from '#/api/request';
 | 
					import { requestClient } from '#/api/request';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export namespace CrmProductCategoryApi {
 | 
					export namespace CrmProductCategoryApi {
 | 
				
			||||||
| 
						 | 
					@ -38,7 +36,7 @@ export function deleteProductCategory(id: number) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 产品分类列表 */
 | 
					/** 产品分类列表 */
 | 
				
			||||||
export function getProductCategoryList(params?: PageParam) {
 | 
					export function getProductCategoryList(params?: any) {
 | 
				
			||||||
  return requestClient.get<CrmProductCategoryApi.ProductCategory[]>(
 | 
					  return requestClient.get<CrmProductCategoryApi.ProductCategory[]>(
 | 
				
			||||||
    '/crm/product-category/list',
 | 
					    '/crm/product-category/list',
 | 
				
			||||||
    { params },
 | 
					    { params },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,5 @@
 | 
				
			||||||
import type { Ref } from 'vue';
 | 
					import type { Ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import type { VbenFormSchema } from '#/adapter/form';
 | 
					 | 
				
			||||||
import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
					 | 
				
			||||||
import type { CrmReceivableApi } from '#/api/crm/receivable';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { useAccess } from '@vben/access';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { DICT_TYPE } from '#/utils';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const { hasAccessByCodes } = useAccess();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface LeftSideItem {
 | 
					export interface LeftSideItem {
 | 
				
			||||||
  name: string;
 | 
					  name: string;
 | 
				
			||||||
  menu: string;
 | 
					  menu: string;
 | 
				
			||||||
| 
						 | 
					@ -109,663 +99,3 @@ export const useLeftSides = (
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 分配给我的线索 列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useClueFollowFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'followUpStatus',
 | 
					 | 
				
			||||||
      label: '状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: FOLLOWUP_STATUS,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: false,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 分配给我的线索 列表的字段 */
 | 
					 | 
				
			||||||
export function useClueFollowColumns(): VxeTableGridOptions['columns'] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'name',
 | 
					 | 
				
			||||||
      title: '线索名称',
 | 
					 | 
				
			||||||
      fixed: 'left',
 | 
					 | 
				
			||||||
      slots: { default: 'name' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'source',
 | 
					 | 
				
			||||||
      title: '线索来源',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'mobile',
 | 
					 | 
				
			||||||
      title: '手机',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'telephone',
 | 
					 | 
				
			||||||
      title: '电话',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'email',
 | 
					 | 
				
			||||||
      title: '邮箱',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'detailAddress',
 | 
					 | 
				
			||||||
      title: '地址',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'industryId',
 | 
					 | 
				
			||||||
      title: '客户行业',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'level',
 | 
					 | 
				
			||||||
      title: '客户级别',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactNextTime',
 | 
					 | 
				
			||||||
      title: '下次联系时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remark',
 | 
					 | 
				
			||||||
      title: '备注',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactLastTime',
 | 
					 | 
				
			||||||
      title: '最后跟进时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactLastContent',
 | 
					 | 
				
			||||||
      title: '最后跟进记录',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserName',
 | 
					 | 
				
			||||||
      title: '负责人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserDeptName',
 | 
					 | 
				
			||||||
      title: '所属部门',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'updateTime',
 | 
					 | 
				
			||||||
      title: '更新时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'createTime',
 | 
					 | 
				
			||||||
      title: '创建时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'creatorName',
 | 
					 | 
				
			||||||
      title: '创建人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 合同审核列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useContractAuditFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'auditStatus',
 | 
					 | 
				
			||||||
      label: '合同状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: AUDIT_STATUS,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 10,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 合同提醒列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useContractRemindFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'expiryType',
 | 
					 | 
				
			||||||
      label: '到期状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: CONTRACT_EXPIRY_TYPE,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 合同审核列表的字段 */
 | 
					 | 
				
			||||||
export function useContractColumns(): VxeTableGridOptions['columns'] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'no',
 | 
					 | 
				
			||||||
      title: '合同编号',
 | 
					 | 
				
			||||||
      fixed: 'left',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'name',
 | 
					 | 
				
			||||||
      title: '合同名称',
 | 
					 | 
				
			||||||
      slots: { default: 'name' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'customerName',
 | 
					 | 
				
			||||||
      title: '客户名称',
 | 
					 | 
				
			||||||
      slots: { default: 'customerName' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'businessName',
 | 
					 | 
				
			||||||
      title: '商机名称',
 | 
					 | 
				
			||||||
      slots: { default: 'businessName' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'price',
 | 
					 | 
				
			||||||
      title: '合同金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'orderDate',
 | 
					 | 
				
			||||||
      title: '下单时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'startTime',
 | 
					 | 
				
			||||||
      title: '合同开始时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'endTime',
 | 
					 | 
				
			||||||
      title: '合同结束时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactName',
 | 
					 | 
				
			||||||
      title: '客户签约人',
 | 
					 | 
				
			||||||
      slots: { default: 'contactName' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'signUserName',
 | 
					 | 
				
			||||||
      title: '公司签约人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remark',
 | 
					 | 
				
			||||||
      title: '备注',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'totalReceivablePrice',
 | 
					 | 
				
			||||||
      title: '已回款金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'noReceivablePrice',
 | 
					 | 
				
			||||||
      title: '未回款金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactLastTime',
 | 
					 | 
				
			||||||
      title: '最后跟进时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserName',
 | 
					 | 
				
			||||||
      title: '负责人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserDeptName',
 | 
					 | 
				
			||||||
      title: '所属部门',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'updateTime',
 | 
					 | 
				
			||||||
      title: '更新时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'createTime',
 | 
					 | 
				
			||||||
      title: '创建时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'creatorName',
 | 
					 | 
				
			||||||
      title: '创建人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'auditStatus',
 | 
					 | 
				
			||||||
      title: '合同状态',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_AUDIT_STATUS },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      title: '操作',
 | 
					 | 
				
			||||||
      width: 80,
 | 
					 | 
				
			||||||
      fixed: 'right',
 | 
					 | 
				
			||||||
      slots: { default: 'actions' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 客户跟进列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useCustomerFollowFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'followUpStatus',
 | 
					 | 
				
			||||||
      label: '状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: FOLLOWUP_STATUS,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: false,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 待进入公海客户列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useCustomerPutPoolFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'sceneType',
 | 
					 | 
				
			||||||
      label: '归属',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: SCENE_TYPES,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 今日需联系客户列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useCustomerTodayContactFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'contactStatus',
 | 
					 | 
				
			||||||
      label: '状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: CONTACT_STATUS,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'sceneType',
 | 
					 | 
				
			||||||
      label: '归属',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: SCENE_TYPES,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 客户列表的字段 */
 | 
					 | 
				
			||||||
export function useCustomerColumns(): VxeTableGridOptions['columns'] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'name',
 | 
					 | 
				
			||||||
      title: '客户名称',
 | 
					 | 
				
			||||||
      slots: { default: 'name' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'source',
 | 
					 | 
				
			||||||
      title: '客户来源',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'mobile',
 | 
					 | 
				
			||||||
      title: '手机',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'telephone',
 | 
					 | 
				
			||||||
      title: '电话',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'email',
 | 
					 | 
				
			||||||
      title: '邮箱',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'level',
 | 
					 | 
				
			||||||
      title: '客户级别',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'industryId',
 | 
					 | 
				
			||||||
      title: '客户行业',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactNextTime',
 | 
					 | 
				
			||||||
      title: '下次联系时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remark',
 | 
					 | 
				
			||||||
      title: '备注',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'lockStatus',
 | 
					 | 
				
			||||||
      title: '锁定状态',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'dealStatus',
 | 
					 | 
				
			||||||
      title: '成交状态',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactLastTime',
 | 
					 | 
				
			||||||
      title: '最后跟进时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contactLastContent',
 | 
					 | 
				
			||||||
      title: '最后跟进记录',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'detailAddress',
 | 
					 | 
				
			||||||
      title: '地址',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'poolDay',
 | 
					 | 
				
			||||||
      title: '距离进入公海天数',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserName',
 | 
					 | 
				
			||||||
      title: '负责人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserDeptName',
 | 
					 | 
				
			||||||
      title: '所属部门',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'updateTime',
 | 
					 | 
				
			||||||
      title: '更新时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'createTime',
 | 
					 | 
				
			||||||
      title: '创建时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'creatorName',
 | 
					 | 
				
			||||||
      title: '创建人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 回款审核列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useReceivableAuditFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'auditStatus',
 | 
					 | 
				
			||||||
      label: '合同状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: AUDIT_STATUS,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 10,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 回款审核列表的字段 */
 | 
					 | 
				
			||||||
export function useReceivableAuditColumns<T = CrmReceivableApi.Receivable>(
 | 
					 | 
				
			||||||
  onActionClick: OnActionClickFn<T>,
 | 
					 | 
				
			||||||
): VxeTableGridOptions['columns'] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'no',
 | 
					 | 
				
			||||||
      title: '回款编号',
 | 
					 | 
				
			||||||
      fixed: 'left',
 | 
					 | 
				
			||||||
      slots: { default: 'no' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'customerName',
 | 
					 | 
				
			||||||
      title: '客户名称',
 | 
					 | 
				
			||||||
      slots: { default: 'customerName' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contractNo',
 | 
					 | 
				
			||||||
      title: '合同编号',
 | 
					 | 
				
			||||||
      slots: { default: 'contractNo' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'returnTime',
 | 
					 | 
				
			||||||
      title: '回款日期',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'price',
 | 
					 | 
				
			||||||
      title: '回款金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'returnType',
 | 
					 | 
				
			||||||
      title: '回款方式',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remark',
 | 
					 | 
				
			||||||
      title: '备注',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contract.totalPrice',
 | 
					 | 
				
			||||||
      title: '合同金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserName',
 | 
					 | 
				
			||||||
      title: '负责人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserDeptName',
 | 
					 | 
				
			||||||
      title: '所属部门',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'updateTime',
 | 
					 | 
				
			||||||
      title: '更新时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'createTime',
 | 
					 | 
				
			||||||
      title: '创建时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'creatorName',
 | 
					 | 
				
			||||||
      title: '创建人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'auditStatus',
 | 
					 | 
				
			||||||
      title: '回款状态',
 | 
					 | 
				
			||||||
      fixed: 'right',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_AUDIT_STATUS },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'operation',
 | 
					 | 
				
			||||||
      title: '操作',
 | 
					 | 
				
			||||||
      width: 140,
 | 
					 | 
				
			||||||
      fixed: 'right',
 | 
					 | 
				
			||||||
      align: 'center',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        attrs: {
 | 
					 | 
				
			||||||
          nameField: 'name',
 | 
					 | 
				
			||||||
          nameTitle: '角色',
 | 
					 | 
				
			||||||
          onClick: onActionClick,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        name: 'CellOperation',
 | 
					 | 
				
			||||||
        options: [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            code: 'processDetail',
 | 
					 | 
				
			||||||
            text: '查看审批',
 | 
					 | 
				
			||||||
            show: hasAccessByCodes(['crm:receivable:update']),
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 回款计划提醒列表的搜索表单 */
 | 
					 | 
				
			||||||
export function useReceivablePlanRemindFormSchema(): VbenFormSchema[] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      fieldName: 'remindType',
 | 
					 | 
				
			||||||
      label: '合同状态',
 | 
					 | 
				
			||||||
      component: 'Select',
 | 
					 | 
				
			||||||
      componentProps: {
 | 
					 | 
				
			||||||
        allowClear: true,
 | 
					 | 
				
			||||||
        options: RECEIVABLE_REMIND_TYPE,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      defaultValue: 1,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 回款计划提醒列表的字段 */
 | 
					 | 
				
			||||||
export function useReceivablePlanRemindColumns<T = CrmReceivableApi.Receivable>(
 | 
					 | 
				
			||||||
  onActionClick: OnActionClickFn<T>,
 | 
					 | 
				
			||||||
): VxeTableGridOptions['columns'] {
 | 
					 | 
				
			||||||
  return [
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'customerName',
 | 
					 | 
				
			||||||
      title: '客户名称',
 | 
					 | 
				
			||||||
      fixed: 'left',
 | 
					 | 
				
			||||||
      slots: { default: 'customerName' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'contractNo',
 | 
					 | 
				
			||||||
      title: '合同编号',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'period',
 | 
					 | 
				
			||||||
      title: '期数',
 | 
					 | 
				
			||||||
      slots: { default: 'period' },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'price',
 | 
					 | 
				
			||||||
      title: '计划回款金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'returnTime',
 | 
					 | 
				
			||||||
      title: '计划回款日期',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remindDays',
 | 
					 | 
				
			||||||
      title: '提前几天提醒',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remindTime',
 | 
					 | 
				
			||||||
      title: '提醒日期',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'returnType',
 | 
					 | 
				
			||||||
      title: '回款方式',
 | 
					 | 
				
			||||||
      fixed: 'right',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        name: 'CellDict',
 | 
					 | 
				
			||||||
        props: { type: DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'remark',
 | 
					 | 
				
			||||||
      title: '备注',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'ownerUserName',
 | 
					 | 
				
			||||||
      title: '负责人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'receivable.price',
 | 
					 | 
				
			||||||
      title: '实际回款金额(元)',
 | 
					 | 
				
			||||||
      formatter: 'formatNumber',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'receivable.returnTime',
 | 
					 | 
				
			||||||
      title: '实际回款日期',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'updateTime',
 | 
					 | 
				
			||||||
      title: '更新时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'createTime',
 | 
					 | 
				
			||||||
      title: '创建时间',
 | 
					 | 
				
			||||||
      formatter: 'formatDateTime',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'creatorName',
 | 
					 | 
				
			||||||
      title: '创建人',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
      field: 'operation',
 | 
					 | 
				
			||||||
      title: '操作',
 | 
					 | 
				
			||||||
      width: 140,
 | 
					 | 
				
			||||||
      fixed: 'right',
 | 
					 | 
				
			||||||
      align: 'center',
 | 
					 | 
				
			||||||
      cellRender: {
 | 
					 | 
				
			||||||
        attrs: {
 | 
					 | 
				
			||||||
          nameField: 'customerName',
 | 
					 | 
				
			||||||
          nameTitle: '客户名称',
 | 
					 | 
				
			||||||
          onClick: onActionClick,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        name: 'CellOperation',
 | 
					 | 
				
			||||||
        options: [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            code: 'receivableForm',
 | 
					 | 
				
			||||||
            text: '创建回款',
 | 
					 | 
				
			||||||
            show: hasAccessByCodes(['crm:receivable:create']),
 | 
					 | 
				
			||||||
          },
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,17 +10,16 @@ import * as ContractApi from '#/api/crm/contract';
 | 
				
			||||||
import * as CustomerApi from '#/api/crm/customer';
 | 
					import * as CustomerApi from '#/api/crm/customer';
 | 
				
			||||||
import * as ReceivableApi from '#/api/crm/receivable';
 | 
					import * as ReceivableApi from '#/api/crm/receivable';
 | 
				
			||||||
import * as ReceivablePlanApi from '#/api/crm/receivable/plan';
 | 
					import * as ReceivablePlanApi from '#/api/crm/receivable/plan';
 | 
				
			||||||
import { DocAlert } from '#/components/doc-alert';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useLeftSides } from './data';
 | 
					import { useLeftSides } from './data';
 | 
				
			||||||
import ClueFollowList from './modules/clue-follow-list.vue';
 | 
					import ClueFollowList from './modules/clue-follow-list.vue';
 | 
				
			||||||
import ContractAuditList from './modules/contract-audit-list.vue';
 | 
					import ContractAuditList from './modules/contract-audit-list.vue';
 | 
				
			||||||
import ContractRemindList from './modules/ContractRemindList.vue';
 | 
					import ContractRemindList from './modules/contract-remind-list.vue';
 | 
				
			||||||
import CustomerFollowList from './modules/CustomerFollowList.vue';
 | 
					import CustomerFollowList from './modules/customer-follow-list.vue';
 | 
				
			||||||
import CustomerPutPoolRemindList from './modules/CustomerPutPoolRemindList.vue';
 | 
					import CustomerPutPoolRemindList from './modules/customer-put-pool-remind-list.vue';
 | 
				
			||||||
import CustomerTodayContactList from './modules/CustomerTodayContactList.vue';
 | 
					import CustomerTodayContactList from './modules/customer-today-contact-list.vue';
 | 
				
			||||||
import ReceivableAuditList from './modules/ReceivableAuditList.vue';
 | 
					import ReceivableAuditList from './modules/receivable-audit-list.vue';
 | 
				
			||||||
import ReceivablePlanRemindList from './modules/ReceivablePlanRemindList.vue';
 | 
					import ReceivablePlanRemindList from './modules/receivable-plan-remind-list.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineOptions({ name: 'CrmBacklog' });
 | 
					defineOptions({ name: 'CrmBacklog' });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -92,12 +91,6 @@ onMounted(async () => {
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Page auto-content-height>
 | 
					  <Page auto-content-height>
 | 
				
			||||||
    <template #doc>
 | 
					 | 
				
			||||||
      <DocAlert
 | 
					 | 
				
			||||||
        title="【通用】跟进记录、待办事项"
 | 
					 | 
				
			||||||
        url="https://doc.iocoder.cn/crm/follow-up/"
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
    </template>
 | 
					 | 
				
			||||||
    <div class="flex h-full w-full">
 | 
					    <div class="flex h-full w-full">
 | 
				
			||||||
      <Card class="w-1/5">
 | 
					      <Card class="w-1/5">
 | 
				
			||||||
        <List item-layout="horizontal" :data-source="leftSides">
 | 
					        <List item-layout="horizontal" :data-source="leftSides">
 | 
				
			||||||
| 
						 | 
					@ -105,11 +98,17 @@ onMounted(async () => {
 | 
				
			||||||
            <List.Item>
 | 
					            <List.Item>
 | 
				
			||||||
              <List.Item.Meta>
 | 
					              <List.Item.Meta>
 | 
				
			||||||
                <template #title>
 | 
					                <template #title>
 | 
				
			||||||
                  <a @click="sideClick(item)"> {{ item.name }} </a>
 | 
					                  <a @click="sideClick(item)">
 | 
				
			||||||
 | 
					                    {{ item.name }}
 | 
				
			||||||
 | 
					                  </a>
 | 
				
			||||||
                </template>
 | 
					                </template>
 | 
				
			||||||
              </List.Item.Meta>
 | 
					              </List.Item.Meta>
 | 
				
			||||||
              <template #extra v-if="item.count.value && item.count.value > 0">
 | 
					              <template #extra>
 | 
				
			||||||
                <Badge :count="item.count.value" />
 | 
					                <Badge
 | 
				
			||||||
 | 
					                  :color="item.menu === leftMenu ? 'blue' : 'red'"
 | 
				
			||||||
 | 
					                  :count="item.count.value"
 | 
				
			||||||
 | 
					                  :show-zero="true"
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
              </template>
 | 
					              </template>
 | 
				
			||||||
            </List.Item>
 | 
					            </List.Item>
 | 
				
			||||||
          </template>
 | 
					          </template>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,90 +0,0 @@
 | 
				
			||||||
<!-- 待回款提醒 -->
 | 
					 | 
				
			||||||
<script lang="ts" setup>
 | 
					 | 
				
			||||||
import type { OnActionClickParams } from '#/adapter/vxe-table';
 | 
					 | 
				
			||||||
import type { CrmReceivableApi } from '#/api/crm/receivable';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { Button } from 'ant-design-vue';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					 | 
				
			||||||
import { getReceivablePage } from '#/api/crm/receivable';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  useReceivablePlanRemindColumns,
 | 
					 | 
				
			||||||
  useReceivablePlanRemindFormSchema,
 | 
					 | 
				
			||||||
} from '../data';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const { push } = useRouter();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 打开回款详情 */
 | 
					 | 
				
			||||||
function openDetail(row: CrmReceivableApi.Receivable) {
 | 
					 | 
				
			||||||
  push({ name: 'CrmReceivableDetail', params: { id: row.id } });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 打开客户详情 */
 | 
					 | 
				
			||||||
function openCustomerDetail(row: CrmReceivableApi.Receivable) {
 | 
					 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 创建回款 */
 | 
					 | 
				
			||||||
function openReceivableForm(row: CrmReceivableApi.Receivable) {
 | 
					 | 
				
			||||||
  // Todo: 打开创建回款
 | 
					 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** 表格操作按钮的回调函数 */
 | 
					 | 
				
			||||||
function onActionClick({
 | 
					 | 
				
			||||||
  code,
 | 
					 | 
				
			||||||
  row,
 | 
					 | 
				
			||||||
}: OnActionClickParams<CrmReceivableApi.Receivable>) {
 | 
					 | 
				
			||||||
  switch (code) {
 | 
					 | 
				
			||||||
    case 'receivableForm': {
 | 
					 | 
				
			||||||
      openReceivableForm(row);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					 | 
				
			||||||
  formOptions: {
 | 
					 | 
				
			||||||
    schema: useReceivablePlanRemindFormSchema(),
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  gridOptions: {
 | 
					 | 
				
			||||||
    columns: useReceivablePlanRemindColumns(onActionClick),
 | 
					 | 
				
			||||||
    height: 'auto',
 | 
					 | 
				
			||||||
    keepSource: true,
 | 
					 | 
				
			||||||
    proxyConfig: {
 | 
					 | 
				
			||||||
      ajax: {
 | 
					 | 
				
			||||||
        query: async ({ page }, formValues) => {
 | 
					 | 
				
			||||||
          return await getReceivablePage({
 | 
					 | 
				
			||||||
            pageNo: page.currentPage,
 | 
					 | 
				
			||||||
            pageSize: page.pageSize,
 | 
					 | 
				
			||||||
            ...formValues,
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    rowConfig: {
 | 
					 | 
				
			||||||
      keyField: 'id',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    toolbarConfig: {
 | 
					 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					 | 
				
			||||||
      search: true,
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<template>
 | 
					 | 
				
			||||||
  <Grid table-title="待回款提醒">
 | 
					 | 
				
			||||||
    <template #customerName="{ row }">
 | 
					 | 
				
			||||||
      <Button type="link" @click="openCustomerDetail(row)">
 | 
					 | 
				
			||||||
        {{ row.customerName }}
 | 
					 | 
				
			||||||
      </Button>
 | 
					 | 
				
			||||||
    </template>
 | 
					 | 
				
			||||||
    <template #period="{ row }">
 | 
					 | 
				
			||||||
      <Button type="link" @click="openDetail(row)">{{ row.period }}</Button>
 | 
					 | 
				
			||||||
    </template>
 | 
					 | 
				
			||||||
  </Grid>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<!-- 分配给我的线索 -->
 | 
					<!-- 分配给我的线索 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmClueApi } from '#/api/crm/clue';
 | 
					import type { CrmClueApi } from '#/api/crm/clue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -8,8 +9,9 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getCluePage } from '#/api/crm/clue';
 | 
					import { getCluePage } from '#/api/crm/clue';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/clue/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useClueFollowColumns, useClueFollowFormSchema } from '../data';
 | 
					import { FOLLOWUP_STATUS } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,10 +22,21 @@ function handleDetail(row: CrmClueApi.Clue) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useClueFollowFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'followUpStatus',
 | 
				
			||||||
 | 
					        label: '状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: FOLLOWUP_STATUS,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: false,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useClueFollowColumns(),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -45,14 +58,17 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmClueApi.Clue>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="分配给我的线索">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
 | 
					      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <Button type="link" @click="handleDetail(row)">查看详情</Button>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<!-- 待审核合同 -->
 | 
					<!-- 待审核合同 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmContractApi } from '#/api/crm/contract';
 | 
					import type { CrmContractApi } from '#/api/crm/contract';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -8,8 +9,9 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getContractPage } from '#/api/crm/contract';
 | 
					import { getContractPage } from '#/api/crm/contract';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/contract/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useContractAuditFormSchema, useContractColumns } from '../data';
 | 
					import { AUDIT_STATUS } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,10 +44,21 @@ function handleBusinessDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useContractAuditFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'auditStatus',
 | 
				
			||||||
 | 
					        label: '合同状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: AUDIT_STATUS,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 10,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useContractColumns(),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -67,12 +80,12 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmContractApi.Contract>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="待审核合同">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="handleContractDetail(row)">
 | 
					      <Button type="link" @click="handleContractDetail(row)">
 | 
				
			||||||
        {{ row.name }}
 | 
					        {{ row.name }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,22 @@
 | 
				
			||||||
<!-- 即将到期的合同 -->
 | 
					<!-- 即将到期的合同 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import type { OnActionClickParams } from '#/adapter/vxe-table';
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmContractApi } from '#/api/crm/contract';
 | 
					import type { CrmContractApi } from '#/api/crm/contract';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Button } from 'ant-design-vue';
 | 
					import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getContractPage } from '#/api/crm/contract';
 | 
					import { getContractPage } from '#/api/crm/contract';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/contract/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useContractColumns, useContractRemindFormSchema } from '../data';
 | 
					import { CONTRACT_EXPIRY_TYPE } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 查看审批 */
 | 
					/** 查看审批 */
 | 
				
			||||||
function openProcessDetail(row: CrmContractApi.Contract) {
 | 
					function handleProcessDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
  push({
 | 
					  push({
 | 
				
			||||||
    name: 'BpmProcessInstanceDetail',
 | 
					    name: 'BpmProcessInstanceDetail',
 | 
				
			||||||
    query: { id: row.processInstanceId },
 | 
					    query: { id: row.processInstanceId },
 | 
				
			||||||
| 
						 | 
					@ -23,43 +24,41 @@ function openProcessDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开合同详情 */
 | 
					/** 打开合同详情 */
 | 
				
			||||||
function openContractDetail(row: CrmContractApi.Contract) {
 | 
					function handleContractDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
  push({ name: 'CrmContractDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmContractDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/** 打开客户详情 */
 | 
					/** 打开客户详情 */
 | 
				
			||||||
function openCustomerDetail(row: CrmContractApi.Contract) {
 | 
					function handleCustomerDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开联系人详情 */
 | 
					/** 打开联系人详情 */
 | 
				
			||||||
function openContactDetail(row: CrmContractApi.Contract) {
 | 
					function handleContactDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
  push({ name: 'CrmContactDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmContactDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开商机详情 */
 | 
					/** 打开商机详情 */
 | 
				
			||||||
function openBusinessDetail(row: CrmContractApi.Contract) {
 | 
					function handleBusinessDetail(row: CrmContractApi.Contract) {
 | 
				
			||||||
  push({ name: 'CrmBusinessDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmBusinessDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 表格操作按钮的回调函数 */
 | 
					 | 
				
			||||||
function onActionClick({
 | 
					 | 
				
			||||||
  code,
 | 
					 | 
				
			||||||
  row,
 | 
					 | 
				
			||||||
}: OnActionClickParams<CrmContractApi.Contract>) {
 | 
					 | 
				
			||||||
  switch (code) {
 | 
					 | 
				
			||||||
    case 'processDetail': {
 | 
					 | 
				
			||||||
      openProcessDetail(row);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useContractRemindFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'expiryType',
 | 
				
			||||||
 | 
					        label: '到期状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: CONTRACT_EXPIRY_TYPE,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 1,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useContractColumns(onActionClick),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -81,31 +80,43 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmContractApi.Contract>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="即将到期的合同">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openContractDetail(row)">
 | 
					      <Button type="link" @click="handleContractDetail(row)">
 | 
				
			||||||
        {{ row.name }}
 | 
					        {{ row.name }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #customerName="{ row }">
 | 
					    <template #customerName="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openCustomerDetail(row)">
 | 
					      <Button type="link" @click="handleCustomerDetail(row)">
 | 
				
			||||||
        {{ row.customerName }}
 | 
					        {{ row.customerName }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #businessName="{ row }">
 | 
					    <template #businessName="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openBusinessDetail(row)">
 | 
					      <Button type="link" @click="handleBusinessDetail(row)">
 | 
				
			||||||
        {{ row.businessName }}
 | 
					        {{ row.businessName }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #contactName="{ row }">
 | 
					    <template #signContactName="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openContactDetail(row)">
 | 
					      <Button type="link" @click="handleContactDetail(row)">
 | 
				
			||||||
        {{ row.contactName }}
 | 
					        {{ row.signContactName }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <TableAction
 | 
				
			||||||
 | 
					        :actions="[
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            label: '查看审批',
 | 
				
			||||||
 | 
					            type: 'link',
 | 
				
			||||||
 | 
					            auth: ['crm:contract:update'],
 | 
				
			||||||
 | 
					            onClick: handleProcessDetail.bind(null, row),
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ]"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<!-- 分配给我的客户 -->
 | 
					<!-- 分配给我的客户 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
					import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -8,22 +9,34 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getCustomerPage } from '#/api/crm/customer';
 | 
					import { getCustomerPage } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/customer/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useCustomerColumns, useCustomerFollowFormSchema } from '../data';
 | 
					import { FOLLOWUP_STATUS } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开客户详情 */
 | 
					/** 打开客户详情 */
 | 
				
			||||||
function onDetail(row: CrmCustomerApi.Customer) {
 | 
					function handleDetail(row: CrmCustomerApi.Customer) {
 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useCustomerFollowFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'followUpStatus',
 | 
				
			||||||
 | 
					        label: '状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: FOLLOWUP_STATUS,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: false,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useCustomerColumns(),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -45,14 +58,17 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmCustomerApi.Customer>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="分配给我的客户">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="onDetail(row)">{{ row.name }}</Button>
 | 
					      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <Button type="link" @click="handleDetail(row)">查看详情</Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<!-- 待进入公海的客户 -->
 | 
					<!-- 待进入公海的客户 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
					import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -8,22 +9,34 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getCustomerPage } from '#/api/crm/customer';
 | 
					import { getCustomerPage } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/customer/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useCustomerColumns, useCustomerPutPoolFormSchema } from '../data';
 | 
					import { SCENE_TYPES } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开客户详情 */
 | 
					/** 打开客户详情 */
 | 
				
			||||||
function onDetail(row: CrmCustomerApi.Customer) {
 | 
					function handleDetail(row: CrmCustomerApi.Customer) {
 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useCustomerPutPoolFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'sceneType',
 | 
				
			||||||
 | 
					        label: '归属',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: SCENE_TYPES,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 1,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useCustomerColumns(),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -45,14 +58,17 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmCustomerApi.Customer>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="待进入公海的客户">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="onDetail(row)">{{ row.name }}</Button>
 | 
					      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <Button type="link" @click="handleDetail(row)">查看详情</Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
<!-- 今日需联系客户 -->
 | 
					<!-- 今日需联系客户 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
					import type { CrmCustomerApi } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -8,22 +9,44 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getCustomerPage } from '#/api/crm/customer';
 | 
					import { getCustomerPage } from '#/api/crm/customer';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/customer/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useCustomerColumns, useCustomerTodayContactFormSchema } from '../data';
 | 
					import { CONTACT_STATUS, SCENE_TYPES } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开客户详情 */
 | 
					/** 打开客户详情 */
 | 
				
			||||||
function onDetail(row: CrmCustomerApi.Customer) {
 | 
					function handleDetail(row: CrmCustomerApi.Customer) {
 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useCustomerTodayContactFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'contactStatus',
 | 
				
			||||||
 | 
					        label: '状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: CONTACT_STATUS,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 1,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'sceneType',
 | 
				
			||||||
 | 
					        label: '归属',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: SCENE_TYPES,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 1,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useCustomerColumns(),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -45,14 +68,17 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmCustomerApi.Customer>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="今日需联系客户">
 | 
					  <Grid>
 | 
				
			||||||
    <template #name="{ row }">
 | 
					    <template #name="{ row }">
 | 
				
			||||||
      <Button type="link" @click="onDetail(row)">{{ row.name }}</Button>
 | 
					      <Button type="link" @click="handleDetail(row)">{{ row.name }}</Button>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <Button type="link" @click="handleDetail(row)">查看详情</Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<!-- 待审核回款 -->
 | 
					<!-- 待审核回款 -->
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import type { OnActionClickParams } from '#/adapter/vxe-table';
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
import type { CrmReceivableApi } from '#/api/crm/receivable';
 | 
					import type { CrmReceivableApi } from '#/api/crm/receivable';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useRouter } from 'vue-router';
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
| 
						 | 
					@ -9,16 +9,14 @@ import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
import { getReceivablePage } from '#/api/crm/receivable';
 | 
					import { getReceivablePage } from '#/api/crm/receivable';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/receivable/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {
 | 
					import { AUDIT_STATUS } from '../data';
 | 
				
			||||||
  useReceivableAuditColumns,
 | 
					 | 
				
			||||||
  useReceivableAuditFormSchema,
 | 
					 | 
				
			||||||
} from '../data';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { push } = useRouter();
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 查看审批 */
 | 
					/** 查看审批 */
 | 
				
			||||||
function openProcessDetail(row: CrmReceivableApi.Receivable) {
 | 
					function handleProcessDetail(row: CrmReceivableApi.Receivable) {
 | 
				
			||||||
  push({
 | 
					  push({
 | 
				
			||||||
    name: 'BpmProcessInstanceDetail',
 | 
					    name: 'BpmProcessInstanceDetail',
 | 
				
			||||||
    query: { id: row.processInstanceId },
 | 
					    query: { id: row.processInstanceId },
 | 
				
			||||||
| 
						 | 
					@ -26,39 +24,37 @@ function openProcessDetail(row: CrmReceivableApi.Receivable) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开回款详情 */
 | 
					/** 打开回款详情 */
 | 
				
			||||||
function openDetail(row: CrmReceivableApi.Receivable) {
 | 
					function handleDetail(row: CrmReceivableApi.Receivable) {
 | 
				
			||||||
  push({ name: 'CrmReceivableDetail', params: { id: row.id } });
 | 
					  push({ name: 'CrmReceivableDetail', params: { id: row.id } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开客户详情 */
 | 
					/** 打开客户详情 */
 | 
				
			||||||
function openCustomerDetail(row: CrmReceivableApi.Receivable) {
 | 
					function handleCustomerDetail(row: CrmReceivableApi.Receivable) {
 | 
				
			||||||
  push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 打开合同详情 */
 | 
					/** 打开合同详情 */
 | 
				
			||||||
function openContractDetail(row: CrmReceivableApi.Receivable) {
 | 
					function handleContractDetail(row: CrmReceivableApi.Receivable) {
 | 
				
			||||||
  push({ name: 'CrmContractDetail', params: { id: row.contractId } });
 | 
					  push({ name: 'CrmContractDetail', params: { id: row.contractId } });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** 表格操作按钮的回调函数 */
 | 
					 | 
				
			||||||
function onActionClick({
 | 
					 | 
				
			||||||
  code,
 | 
					 | 
				
			||||||
  row,
 | 
					 | 
				
			||||||
}: OnActionClickParams<CrmReceivableApi.Receivable>) {
 | 
					 | 
				
			||||||
  switch (code) {
 | 
					 | 
				
			||||||
    case 'processDetail': {
 | 
					 | 
				
			||||||
      openProcessDetail(row);
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const [Grid] = useVbenVxeGrid({
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
  formOptions: {
 | 
					  formOptions: {
 | 
				
			||||||
    schema: useReceivableAuditFormSchema(),
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'auditStatus',
 | 
				
			||||||
 | 
					        label: '合同状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: AUDIT_STATUS,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 10,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  gridOptions: {
 | 
					  gridOptions: {
 | 
				
			||||||
    columns: useReceivableAuditColumns(onActionClick),
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
    height: 'auto',
 | 
					    height: 'auto',
 | 
				
			||||||
    keepSource: true,
 | 
					    keepSource: true,
 | 
				
			||||||
    proxyConfig: {
 | 
					    proxyConfig: {
 | 
				
			||||||
| 
						 | 
					@ -79,26 +75,29 @@ const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
      refresh: { code: 'query' },
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
      search: true,
 | 
					      search: true,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
  },
 | 
					  } as VxeTableGridOptions<CrmReceivableApi.Receivable>,
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Grid table-title="待审核回款">
 | 
					  <Grid>
 | 
				
			||||||
    <template #no="{ row }">
 | 
					    <template #no="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openDetail(row)">
 | 
					      <Button type="link" @click="handleDetail(row)">
 | 
				
			||||||
        {{ row.no }}
 | 
					        {{ row.no }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #customerName="{ row }">
 | 
					    <template #customerName="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openCustomerDetail(row)">
 | 
					      <Button type="link" @click="handleCustomerDetail(row)">
 | 
				
			||||||
        {{ row.customerName }}
 | 
					        {{ row.customerName }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
    <template #contractNo="{ row }">
 | 
					    <template #contractNo="{ row }">
 | 
				
			||||||
      <Button type="link" @click="openContractDetail(row)">
 | 
					      <Button type="link" @click="handleContractDetail(row)">
 | 
				
			||||||
        {{ row.contractNo }}
 | 
					        {{ row.contractNo }}
 | 
				
			||||||
      </Button>
 | 
					      </Button>
 | 
				
			||||||
    </template>
 | 
					    </template>
 | 
				
			||||||
 | 
					    <template #actions="{ row }">
 | 
				
			||||||
 | 
					      <Button type="link" @click="handleProcessDetail(row)">查看审批</Button>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
  </Grid>
 | 
					  </Grid>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,101 @@
 | 
				
			||||||
 | 
					<!-- 待回款提醒 -->
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import type { CrmReceivablePlanApi } from '#/api/crm/receivable/plan';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useRouter } from 'vue-router';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenModal } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Button } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import { getReceivablePlanPage } from '#/api/crm/receivable/plan';
 | 
				
			||||||
 | 
					import Form from '#/views/crm/receivable/modules/form.vue';
 | 
				
			||||||
 | 
					import { useGridColumns } from '#/views/crm/receivable/plan/data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { RECEIVABLE_REMIND_TYPE } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { push } = useRouter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [FormModal, formModalApi] = useVbenModal({
 | 
				
			||||||
 | 
					  connectedComponent: Form,
 | 
				
			||||||
 | 
					  destroyOnClose: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 打开回款详情 */
 | 
				
			||||||
 | 
					function handleDetail(row: CrmReceivablePlanApi.Plan) {
 | 
				
			||||||
 | 
					  push({ name: 'CrmReceivableDetail', params: { id: row.id } });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 打开客户详情 */
 | 
				
			||||||
 | 
					function handleCustomerDetail(row: CrmReceivablePlanApi.Plan) {
 | 
				
			||||||
 | 
					  push({ name: 'CrmCustomerDetail', params: { id: row.customerId } });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 创建回款 */
 | 
				
			||||||
 | 
					function handleCreateReceivable(row: CrmReceivablePlanApi.Plan) {
 | 
				
			||||||
 | 
					  formModalApi.setData({ plan: row }).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Grid] = useVbenVxeGrid({
 | 
				
			||||||
 | 
					  formOptions: {
 | 
				
			||||||
 | 
					    schema: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        fieldName: 'remindType',
 | 
				
			||||||
 | 
					        label: '合同状态',
 | 
				
			||||||
 | 
					        component: 'Select',
 | 
				
			||||||
 | 
					        componentProps: {
 | 
				
			||||||
 | 
					          allowClear: true,
 | 
				
			||||||
 | 
					          options: RECEIVABLE_REMIND_TYPE,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        defaultValue: 1,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  gridOptions: {
 | 
				
			||||||
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
 | 
					    height: 'auto',
 | 
				
			||||||
 | 
					    keepSource: true,
 | 
				
			||||||
 | 
					    proxyConfig: {
 | 
				
			||||||
 | 
					      ajax: {
 | 
				
			||||||
 | 
					        query: async ({ page }, formValues) => {
 | 
				
			||||||
 | 
					          return await getReceivablePlanPage({
 | 
				
			||||||
 | 
					            pageNo: page.currentPage,
 | 
				
			||||||
 | 
					            pageSize: page.pageSize,
 | 
				
			||||||
 | 
					            ...formValues,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    rowConfig: {
 | 
				
			||||||
 | 
					      keyField: 'id',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    toolbarConfig: {
 | 
				
			||||||
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
 | 
					      search: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  } as VxeTableGridOptions<CrmReceivablePlanApi.Plan>,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <div>
 | 
				
			||||||
 | 
					    <FormModal />
 | 
				
			||||||
 | 
					    <Grid>
 | 
				
			||||||
 | 
					      <template #customerName="{ row }">
 | 
				
			||||||
 | 
					        <Button type="link" @click="handleCustomerDetail(row)">
 | 
				
			||||||
 | 
					          {{ row.customerName }}
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <template #period="{ row }">
 | 
				
			||||||
 | 
					        <Button type="link" @click="handleDetail(row)">{{ row.period }}</Button>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <template #actions="{ row }">
 | 
				
			||||||
 | 
					        <Button type="link" @click="handleCreateReceivable(row)">
 | 
				
			||||||
 | 
					          创建回款
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,140 @@
 | 
				
			||||||
 | 
					import type { VbenFormSchema } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { handleTree } from '@vben/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { LimitConfType } from '#/api/crm/customer/limitConfig';
 | 
				
			||||||
 | 
					import { getSimpleDeptList } from '#/api/system/dept';
 | 
				
			||||||
 | 
					import { getSimpleUserList } from '#/api/system/user';
 | 
				
			||||||
 | 
					import { DICT_TYPE } from '#/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 新增/修改的表单 */
 | 
				
			||||||
 | 
					export function useFormSchema(confType: LimitConfType): VbenFormSchema[] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'id',
 | 
				
			||||||
 | 
					      component: 'Input',
 | 
				
			||||||
 | 
					      dependencies: {
 | 
				
			||||||
 | 
					        triggerFields: [''],
 | 
				
			||||||
 | 
					        show: () => false,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'userIds',
 | 
				
			||||||
 | 
					      label: '规则适用人群',
 | 
				
			||||||
 | 
					      component: 'ApiSelect',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        api: getSimpleUserList,
 | 
				
			||||||
 | 
					        fieldNames: {
 | 
				
			||||||
 | 
					          label: 'nickname',
 | 
				
			||||||
 | 
					          value: 'id',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        multiple: true,
 | 
				
			||||||
 | 
					        allowClear: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      rules: 'required',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'deptIds',
 | 
				
			||||||
 | 
					      label: '规则适用部门',
 | 
				
			||||||
 | 
					      component: 'ApiTreeSelect',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        api: async () => {
 | 
				
			||||||
 | 
					          const data = await getSimpleDeptList();
 | 
				
			||||||
 | 
					          return handleTree(data);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        multiple: true,
 | 
				
			||||||
 | 
					        fieldNames: { label: 'name', value: 'id', children: 'children' },
 | 
				
			||||||
 | 
					        placeholder: '请选择规则适用部门',
 | 
				
			||||||
 | 
					        treeDefaultExpandAll: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      rules: 'required',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'maxCount',
 | 
				
			||||||
 | 
					      label:
 | 
				
			||||||
 | 
					        confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT
 | 
				
			||||||
 | 
					          ? '拥有客户数上限'
 | 
				
			||||||
 | 
					          : '锁定客户数上限',
 | 
				
			||||||
 | 
					      component: 'InputNumber',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'dealCountEnabled',
 | 
				
			||||||
 | 
					      label: '成交客户是否占用拥有客户数',
 | 
				
			||||||
 | 
					      component: 'RadioGroup',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        options: [
 | 
				
			||||||
 | 
					          { label: '是', value: true },
 | 
				
			||||||
 | 
					          { label: '否', value: false },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      dependencies: {
 | 
				
			||||||
 | 
					        triggerFields: [''],
 | 
				
			||||||
 | 
					        show: () => confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 列表的字段 */
 | 
				
			||||||
 | 
					export function useGridColumns(
 | 
				
			||||||
 | 
					  confType: LimitConfType,
 | 
				
			||||||
 | 
					): VxeTableGridOptions['columns'] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'id',
 | 
				
			||||||
 | 
					      title: '编号',
 | 
				
			||||||
 | 
					      fixed: 'left',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'users',
 | 
				
			||||||
 | 
					      title: '规则适用人群',
 | 
				
			||||||
 | 
					      formatter: ({ cellValue }) => {
 | 
				
			||||||
 | 
					        return cellValue
 | 
				
			||||||
 | 
					          .map((user: any) => {
 | 
				
			||||||
 | 
					            return user.nickname;
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .join(',');
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'depts',
 | 
				
			||||||
 | 
					      title: '规则适用部门',
 | 
				
			||||||
 | 
					      formatter: ({ cellValue }) => {
 | 
				
			||||||
 | 
					        return cellValue
 | 
				
			||||||
 | 
					          .map((dept: any) => {
 | 
				
			||||||
 | 
					            return dept.name;
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					          .join(',');
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'maxCount',
 | 
				
			||||||
 | 
					      title:
 | 
				
			||||||
 | 
					        confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT
 | 
				
			||||||
 | 
					          ? '拥有客户数上限'
 | 
				
			||||||
 | 
					          : '锁定客户数上限',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'dealCountEnabled',
 | 
				
			||||||
 | 
					      title: '成交客户是否占用拥有客户数',
 | 
				
			||||||
 | 
					      visible: confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT,
 | 
				
			||||||
 | 
					      cellRender: {
 | 
				
			||||||
 | 
					        name: 'CellDict',
 | 
				
			||||||
 | 
					        props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'createTime',
 | 
				
			||||||
 | 
					      title: '创建时间',
 | 
				
			||||||
 | 
					      formatter: 'formatDateTime',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: '操作',
 | 
				
			||||||
 | 
					      width: 180,
 | 
				
			||||||
 | 
					      fixed: 'right',
 | 
				
			||||||
 | 
					      slots: { default: 'actions' },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,38 +1,170 @@
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { Page } from '@vben/common-ui';
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import type { CrmCustomerLimitConfigApi } from '#/api/crm/customer/limitConfig';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Button } from 'ant-design-vue';
 | 
					import { ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Page, useVbenModal } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { message, Tabs } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  deleteCustomerLimitConfig,
 | 
				
			||||||
 | 
					  getCustomerLimitConfigPage,
 | 
				
			||||||
 | 
					  LimitConfType,
 | 
				
			||||||
 | 
					} from '#/api/crm/customer/limitConfig';
 | 
				
			||||||
import { DocAlert } from '#/components/doc-alert';
 | 
					import { DocAlert } from '#/components/doc-alert';
 | 
				
			||||||
 | 
					import { $t } from '#/locales';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useGridColumns } from './data';
 | 
				
			||||||
 | 
					import Form from './modules/form.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const configType = ref(LimitConfType.CUSTOMER_QUANTITY_LIMIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 刷新表格 */
 | 
				
			||||||
 | 
					function onRefresh() {
 | 
				
			||||||
 | 
					  gridApi.query();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [FormModal, formModalApi] = useVbenModal({
 | 
				
			||||||
 | 
					  connectedComponent: Form,
 | 
				
			||||||
 | 
					  destroyOnClose: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 创建规则 */
 | 
				
			||||||
 | 
					function handleCreate(type: LimitConfType) {
 | 
				
			||||||
 | 
					  formModalApi.setData({ type }).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 编辑规则 */
 | 
				
			||||||
 | 
					function handleEdit(
 | 
				
			||||||
 | 
					  row: CrmCustomerLimitConfigApi.CustomerLimitConfig,
 | 
				
			||||||
 | 
					  type: LimitConfType,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  formModalApi.setData({ id: row.id, type }).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 删除规则 */
 | 
				
			||||||
 | 
					async function handleDelete(
 | 
				
			||||||
 | 
					  row: CrmCustomerLimitConfigApi.CustomerLimitConfig,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  const hideLoading = message.loading({
 | 
				
			||||||
 | 
					    content: $t('ui.actionMessage.deleting', [row.id]),
 | 
				
			||||||
 | 
					    key: 'action_key_msg',
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    await deleteCustomerLimitConfig(row.id as number);
 | 
				
			||||||
 | 
					    message.success({
 | 
				
			||||||
 | 
					      content: $t('ui.actionMessage.deleteSuccess', [row.id]),
 | 
				
			||||||
 | 
					      key: 'action_key_msg',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    onRefresh();
 | 
				
			||||||
 | 
					  } finally {
 | 
				
			||||||
 | 
					    hideLoading();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Grid, gridApi] = useVbenVxeGrid({
 | 
				
			||||||
 | 
					  gridOptions: {
 | 
				
			||||||
 | 
					    columns: useGridColumns(configType.value),
 | 
				
			||||||
 | 
					    height: 'auto',
 | 
				
			||||||
 | 
					    keepSource: true,
 | 
				
			||||||
 | 
					    proxyConfig: {
 | 
				
			||||||
 | 
					      ajax: {
 | 
				
			||||||
 | 
					        query: async ({ page }, formValues) => {
 | 
				
			||||||
 | 
					          return await getCustomerLimitConfigPage({
 | 
				
			||||||
 | 
					            page: page.currentPage,
 | 
				
			||||||
 | 
					            pageSize: page.pageSize,
 | 
				
			||||||
 | 
					            type: configType.value,
 | 
				
			||||||
 | 
					            ...formValues,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    rowConfig: {
 | 
				
			||||||
 | 
					      keyField: 'id',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    toolbarConfig: {
 | 
				
			||||||
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
 | 
					      search: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  } as VxeTableGridOptions<CrmCustomerLimitConfigApi.CustomerLimitConfig>,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onChangeConfigType(key: number | string) {
 | 
				
			||||||
 | 
					  configType.value = key as LimitConfType;
 | 
				
			||||||
 | 
					  gridApi.setGridOptions({
 | 
				
			||||||
 | 
					    columns: useGridColumns(configType.value),
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  onRefresh();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Page>
 | 
					  <Page auto-content-height>
 | 
				
			||||||
    <DocAlert
 | 
					    <template #doc>
 | 
				
			||||||
      title="【客户】客户管理、公海客户"
 | 
					      <DocAlert
 | 
				
			||||||
      url="https://doc.iocoder.cn/crm/customer/"
 | 
					        title="【客户】客户管理、公海客户"
 | 
				
			||||||
    />
 | 
					        url="https://doc.iocoder.cn/crm/customer/"
 | 
				
			||||||
    <DocAlert
 | 
					      />
 | 
				
			||||||
      title="【通用】数据权限"
 | 
					      <DocAlert
 | 
				
			||||||
      url="https://doc.iocoder.cn/crm/permission/"
 | 
					        title="【通用】数据权限"
 | 
				
			||||||
    />
 | 
					        url="https://doc.iocoder.cn/crm/permission/"
 | 
				
			||||||
    <Button
 | 
					      />
 | 
				
			||||||
      danger
 | 
					    </template>
 | 
				
			||||||
      type="link"
 | 
					
 | 
				
			||||||
      target="_blank"
 | 
					    <FormModal />
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3"
 | 
					    <Grid>
 | 
				
			||||||
    >
 | 
					      <template #top>
 | 
				
			||||||
      该功能支持 Vue3 + element-plus 版本!
 | 
					        <Tabs class="border-none" @change="onChangeConfigType">
 | 
				
			||||||
    </Button>
 | 
					          <Tabs.TabPane
 | 
				
			||||||
    <br />
 | 
					            tab="拥有客户数限制"
 | 
				
			||||||
    <Button
 | 
					            :key="LimitConfType.CUSTOMER_QUANTITY_LIMIT"
 | 
				
			||||||
      type="link"
 | 
					          />
 | 
				
			||||||
      target="_blank"
 | 
					          <Tabs.TabPane
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/customer/limitConfig/index"
 | 
					            tab="锁定客户数限制"
 | 
				
			||||||
    >
 | 
					            :key="LimitConfType.CUSTOMER_LOCK_LIMIT"
 | 
				
			||||||
      可参考
 | 
					          />
 | 
				
			||||||
      https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/customer/limitConfig/index
 | 
					        </Tabs>
 | 
				
			||||||
      代码,pull request 贡献给我们!
 | 
					      </template>
 | 
				
			||||||
    </Button>
 | 
					      <template #toolbar-tools>
 | 
				
			||||||
 | 
					        <TableAction
 | 
				
			||||||
 | 
					          :actions="[
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: $t('ui.actionTitle.create', ['规则']),
 | 
				
			||||||
 | 
					              type: 'primary',
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.ADD,
 | 
				
			||||||
 | 
					              auth: ['crm:customer-limit-config:create'],
 | 
				
			||||||
 | 
					              onClick: handleCreate.bind(null, configType),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ]"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <template #actions="{ row }">
 | 
				
			||||||
 | 
					        <TableAction
 | 
				
			||||||
 | 
					          :actions="[
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: $t('common.edit'),
 | 
				
			||||||
 | 
					              type: 'link',
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.EDIT,
 | 
				
			||||||
 | 
					              auth: ['crm:customer-limit-config:update'],
 | 
				
			||||||
 | 
					              onClick: handleEdit.bind(null, row, configType),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: $t('common.delete'),
 | 
				
			||||||
 | 
					              type: 'link',
 | 
				
			||||||
 | 
					              danger: true,
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.DELETE,
 | 
				
			||||||
 | 
					              auth: ['crm:customer-limit-config:delete'],
 | 
				
			||||||
 | 
					              popConfirm: {
 | 
				
			||||||
 | 
					                title: $t('ui.actionMessage.deleteConfirm', [row.name]),
 | 
				
			||||||
 | 
					                confirm: handleDelete.bind(null, row),
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ]"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
  </Page>
 | 
					  </Page>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,100 @@
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { CrmCustomerLimitConfigApi } from '#/api/crm/customer/limitConfig';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { computed, ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenModal } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { message } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenForm } from '#/adapter/form';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  createCustomerLimitConfig,
 | 
				
			||||||
 | 
					  getCustomerLimitConfig,
 | 
				
			||||||
 | 
					  LimitConfType,
 | 
				
			||||||
 | 
					  updateCustomerLimitConfig,
 | 
				
			||||||
 | 
					} from '#/api/crm/customer/limitConfig';
 | 
				
			||||||
 | 
					import { $t } from '#/locales';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useFormSchema } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const emit = defineEmits(['success']);
 | 
				
			||||||
 | 
					const formData = ref<CrmCustomerLimitConfigApi.CustomerLimitConfig>();
 | 
				
			||||||
 | 
					const getTitle = computed(() => {
 | 
				
			||||||
 | 
					  return formData.value?.id
 | 
				
			||||||
 | 
					    ? $t('ui.actionTitle.edit', ['规则'])
 | 
				
			||||||
 | 
					    : $t('ui.actionTitle.create', ['规则']);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const confType = ref<LimitConfType>(LimitConfType.CUSTOMER_LOCK_LIMIT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Form, formApi] = useVbenForm({
 | 
				
			||||||
 | 
					  commonConfig: {
 | 
				
			||||||
 | 
					    componentProps: {
 | 
				
			||||||
 | 
					      class: 'w-full',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    formItemClass: 'col-span-2',
 | 
				
			||||||
 | 
					    labelWidth: 120,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  layout: 'horizontal',
 | 
				
			||||||
 | 
					  schema: useFormSchema(confType.value),
 | 
				
			||||||
 | 
					  showDefaultActions: false,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Modal, modalApi] = useVbenModal({
 | 
				
			||||||
 | 
					  async onConfirm() {
 | 
				
			||||||
 | 
					    const { valid } = await formApi.validate();
 | 
				
			||||||
 | 
					    if (!valid) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    modalApi.lock();
 | 
				
			||||||
 | 
					    // 提交表单
 | 
				
			||||||
 | 
					    const data =
 | 
				
			||||||
 | 
					      (await formApi.getValues()) as CrmCustomerLimitConfigApi.CustomerLimitConfig;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await (formData.value?.id
 | 
				
			||||||
 | 
					        ? updateCustomerLimitConfig(data)
 | 
				
			||||||
 | 
					        : createCustomerLimitConfig(data));
 | 
				
			||||||
 | 
					      // 关闭并提示
 | 
				
			||||||
 | 
					      await modalApi.close();
 | 
				
			||||||
 | 
					      emit('success');
 | 
				
			||||||
 | 
					      message.success($t('ui.actionMessage.operationSuccess'));
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      modalApi.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  async onOpenChange(isOpen: boolean) {
 | 
				
			||||||
 | 
					    if (!isOpen) {
 | 
				
			||||||
 | 
					      formData.value = undefined;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 加载数据
 | 
				
			||||||
 | 
					    let data =
 | 
				
			||||||
 | 
					      modalApi.getData<CrmCustomerLimitConfigApi.CustomerLimitConfig>();
 | 
				
			||||||
 | 
					    if (!data) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (data.type) {
 | 
				
			||||||
 | 
					      confType.value = data.type as LimitConfType;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    formApi.setState({ schema: useFormSchema(confType.value) });
 | 
				
			||||||
 | 
					    modalApi.lock();
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if (data.id) {
 | 
				
			||||||
 | 
					        data = await getCustomerLimitConfig(data.id as number);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      formData.value = data;
 | 
				
			||||||
 | 
					      // 设置到 values
 | 
				
			||||||
 | 
					      await formApi.setValues(data);
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      modalApi.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <Modal :title="getTitle" class="w-[40%]">
 | 
				
			||||||
 | 
					    <Form class="mx-4" />
 | 
				
			||||||
 | 
					  </Modal>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,91 @@
 | 
				
			||||||
 | 
					import type { VbenFormSchema } from '#/adapter/form';
 | 
				
			||||||
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import type { CrmProductCategoryApi } from '#/api/crm/product/category';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { handleTree } from '@vben/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { getProductCategoryList } from '#/api/crm/product/category';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 新增/修改的表单 */
 | 
				
			||||||
 | 
					export function useFormSchema(): VbenFormSchema[] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      component: 'Input',
 | 
				
			||||||
 | 
					      fieldName: 'id',
 | 
				
			||||||
 | 
					      dependencies: {
 | 
				
			||||||
 | 
					        triggerFields: [''],
 | 
				
			||||||
 | 
					        show: () => false,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'parentId',
 | 
				
			||||||
 | 
					      label: '上级分类',
 | 
				
			||||||
 | 
					      component: 'ApiTreeSelect',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        allowClear: true,
 | 
				
			||||||
 | 
					        api: async () => {
 | 
				
			||||||
 | 
					          const data = await getProductCategoryList();
 | 
				
			||||||
 | 
					          data.unshift({
 | 
				
			||||||
 | 
					            id: 0,
 | 
				
			||||||
 | 
					            name: '顶级分类',
 | 
				
			||||||
 | 
					          } as CrmProductCategoryApi.ProductCategory);
 | 
				
			||||||
 | 
					          return handleTree(data);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        fieldNames: { label: 'name', value: 'id', children: 'children' },
 | 
				
			||||||
 | 
					        placeholder: '请选择上级分类',
 | 
				
			||||||
 | 
					        showSearch: true,
 | 
				
			||||||
 | 
					        treeDefaultExpandAll: true,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      rules: 'selectRequired',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'name',
 | 
				
			||||||
 | 
					      label: '分类名称',
 | 
				
			||||||
 | 
					      component: 'Input',
 | 
				
			||||||
 | 
					      componentProps: {
 | 
				
			||||||
 | 
					        placeholder: '请输入分类名称',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      rules: 'required',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 列表的搜索表单 */
 | 
				
			||||||
 | 
					export function useGridFormSchema(): VbenFormSchema[] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      fieldName: 'name',
 | 
				
			||||||
 | 
					      label: '分类名称',
 | 
				
			||||||
 | 
					      component: 'Input',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 表格列配置 */
 | 
				
			||||||
 | 
					export function useGridColumns(): VxeTableGridOptions<CrmProductCategoryApi.ProductCategory>['columns'] {
 | 
				
			||||||
 | 
					  return [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'name',
 | 
				
			||||||
 | 
					      title: '分类名称',
 | 
				
			||||||
 | 
					      treeNode: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'id',
 | 
				
			||||||
 | 
					      title: '分类编号',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'createTime',
 | 
				
			||||||
 | 
					      title: '创建时间',
 | 
				
			||||||
 | 
					      formatter: 'formatDateTime',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      field: 'actions',
 | 
				
			||||||
 | 
					      title: '操作',
 | 
				
			||||||
 | 
					      width: 200,
 | 
				
			||||||
 | 
					      fixed: 'right',
 | 
				
			||||||
 | 
					      slots: {
 | 
				
			||||||
 | 
					        default: 'actions',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,34 +1,173 @@
 | 
				
			||||||
<script lang="ts" setup>
 | 
					<script lang="ts" setup>
 | 
				
			||||||
import { Page } from '@vben/common-ui';
 | 
					import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import type { CrmProductCategoryApi } from '#/api/crm/product/category';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Button } from 'ant-design-vue';
 | 
					import { ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Page, useVbenModal } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { message } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  deleteProductCategory,
 | 
				
			||||||
 | 
					  getProductCategoryList,
 | 
				
			||||||
 | 
					} from '#/api/crm/product/category';
 | 
				
			||||||
import { DocAlert } from '#/components/doc-alert';
 | 
					import { DocAlert } from '#/components/doc-alert';
 | 
				
			||||||
 | 
					import { $t } from '#/locales';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useGridColumns, useGridFormSchema } from './data';
 | 
				
			||||||
 | 
					import Form from './modules/form.vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [FormModal, formModalApi] = useVbenModal({
 | 
				
			||||||
 | 
					  connectedComponent: Form,
 | 
				
			||||||
 | 
					  destroyOnClose: true,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 刷新表格 */
 | 
				
			||||||
 | 
					function onRefresh() {
 | 
				
			||||||
 | 
					  gridApi.query();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 创建分类 */
 | 
				
			||||||
 | 
					function handleCreate() {
 | 
				
			||||||
 | 
					  formModalApi.setData({}).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 添加下级分类 */
 | 
				
			||||||
 | 
					function handleAppend(row: CrmProductCategoryApi.ProductCategory) {
 | 
				
			||||||
 | 
					  formModalApi.setData({ parentId: row.id }).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 编辑分类 */
 | 
				
			||||||
 | 
					function handleEdit(row: CrmProductCategoryApi.ProductCategory) {
 | 
				
			||||||
 | 
					  formModalApi.setData(row).open();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 删除分类 */
 | 
				
			||||||
 | 
					async function handleDelete(row: CrmProductCategoryApi.ProductCategory) {
 | 
				
			||||||
 | 
					  const hideLoading = message.loading({
 | 
				
			||||||
 | 
					    content: $t('ui.actionMessage.deleting', [row.name]),
 | 
				
			||||||
 | 
					    key: 'action_key_msg',
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    await deleteProductCategory(row.id as number);
 | 
				
			||||||
 | 
					    message.success({
 | 
				
			||||||
 | 
					      content: $t('ui.actionMessage.deleteSuccess', [row.name]),
 | 
				
			||||||
 | 
					      key: 'action_key_msg',
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    onRefresh();
 | 
				
			||||||
 | 
					  } finally {
 | 
				
			||||||
 | 
					    hideLoading();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 切换树形展开/收缩状态 */
 | 
				
			||||||
 | 
					const isExpanded = ref(false);
 | 
				
			||||||
 | 
					function toggleExpand() {
 | 
				
			||||||
 | 
					  isExpanded.value = !isExpanded.value;
 | 
				
			||||||
 | 
					  gridApi.grid.setAllTreeExpand(isExpanded.value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Grid, gridApi] = useVbenVxeGrid({
 | 
				
			||||||
 | 
					  formOptions: {
 | 
				
			||||||
 | 
					    schema: useGridFormSchema(),
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  gridOptions: {
 | 
				
			||||||
 | 
					    columns: useGridColumns(),
 | 
				
			||||||
 | 
					    height: 'auto',
 | 
				
			||||||
 | 
					    keepSource: true,
 | 
				
			||||||
 | 
					    pagerConfig: {
 | 
				
			||||||
 | 
					      enabled: false,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    proxyConfig: {
 | 
				
			||||||
 | 
					      ajax: {
 | 
				
			||||||
 | 
					        query: async (_, formValues) => {
 | 
				
			||||||
 | 
					          return await getProductCategoryList(formValues);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    rowConfig: {
 | 
				
			||||||
 | 
					      keyField: 'id',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    toolbarConfig: {
 | 
				
			||||||
 | 
					      refresh: { code: 'query' },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    treeConfig: {
 | 
				
			||||||
 | 
					      parentField: 'parentId',
 | 
				
			||||||
 | 
					      rowField: 'id',
 | 
				
			||||||
 | 
					      transform: true,
 | 
				
			||||||
 | 
					      reserve: true,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  } as VxeTableGridOptions<CrmProductCategoryApi.ProductCategory>,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <Page>
 | 
					  <Page auto-content-height>
 | 
				
			||||||
    <DocAlert
 | 
					    <template #doc>
 | 
				
			||||||
      title="【产品】产品管理、产品分类"
 | 
					      <DocAlert
 | 
				
			||||||
      url="https://doc.iocoder.cn/crm/product/"
 | 
					        title="【产品】产品管理、产品分类"
 | 
				
			||||||
    />
 | 
					        url="https://doc.iocoder.cn/crm/product/"
 | 
				
			||||||
    <Button
 | 
					      />
 | 
				
			||||||
      danger
 | 
					    </template>
 | 
				
			||||||
      type="link"
 | 
					
 | 
				
			||||||
      target="_blank"
 | 
					    <FormModal @success="onRefresh" />
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3"
 | 
					    <Grid>
 | 
				
			||||||
    >
 | 
					      <template #toolbar-tools>
 | 
				
			||||||
      该功能支持 Vue3 + element-plus 版本!
 | 
					        <TableAction
 | 
				
			||||||
    </Button>
 | 
					          :actions="[
 | 
				
			||||||
    <br />
 | 
					            {
 | 
				
			||||||
    <Button
 | 
					              label: $t('ui.actionTitle.create', ['分类']),
 | 
				
			||||||
      type="link"
 | 
					              type: 'primary',
 | 
				
			||||||
      target="_blank"
 | 
					              icon: ACTION_ICON.ADD,
 | 
				
			||||||
      href="https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/product/category/index"
 | 
					              auth: ['crm:product-category:create'],
 | 
				
			||||||
    >
 | 
					              onClick: handleCreate,
 | 
				
			||||||
      可参考
 | 
					            },
 | 
				
			||||||
      https://github.com/yudaocode/yudao-ui-admin-vue3/blob/master/src/views/crm/product/category/index
 | 
					            {
 | 
				
			||||||
      代码,pull request 贡献给我们!
 | 
					              label: isExpanded ? '收缩' : '展开',
 | 
				
			||||||
    </Button>
 | 
					              type: 'primary',
 | 
				
			||||||
 | 
					              onClick: toggleExpand,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ]"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <template #name="{ row }">
 | 
				
			||||||
 | 
					        <div class="flex w-full items-center gap-1">
 | 
				
			||||||
 | 
					          <span class="flex-auto">{{ row.name }}</span>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <template #actions="{ row }">
 | 
				
			||||||
 | 
					        <TableAction
 | 
				
			||||||
 | 
					          :actions="[
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: '新增下级',
 | 
				
			||||||
 | 
					              type: 'link',
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.ADD,
 | 
				
			||||||
 | 
					              auth: ['crm:product-category:create'],
 | 
				
			||||||
 | 
					              onClick: handleAppend.bind(null, row),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: $t('common.edit'),
 | 
				
			||||||
 | 
					              type: 'link',
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.EDIT,
 | 
				
			||||||
 | 
					              auth: ['crm:product-category:update'],
 | 
				
			||||||
 | 
					              onClick: handleEdit.bind(null, row),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              label: $t('common.delete'),
 | 
				
			||||||
 | 
					              type: 'link',
 | 
				
			||||||
 | 
					              danger: true,
 | 
				
			||||||
 | 
					              icon: ACTION_ICON.DELETE,
 | 
				
			||||||
 | 
					              auth: ['crm:product-category:delete'],
 | 
				
			||||||
 | 
					              popConfirm: {
 | 
				
			||||||
 | 
					                title: $t('ui.actionMessage.deleteConfirm', [row.name]),
 | 
				
			||||||
 | 
					                confirm: handleDelete.bind(null, row),
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					          ]"
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
  </Page>
 | 
					  </Page>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,92 @@
 | 
				
			||||||
 | 
					<script lang="ts" setup>
 | 
				
			||||||
 | 
					import type { CrmProductCategoryApi } from '#/api/crm/product/category';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { computed, ref } from 'vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenModal } from '@vben/common-ui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { message } from 'ant-design-vue';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useVbenForm } from '#/adapter/form';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  createProductCategory,
 | 
				
			||||||
 | 
					  getProductCategory,
 | 
				
			||||||
 | 
					  updateProductCategory,
 | 
				
			||||||
 | 
					} from '#/api/crm/product/category';
 | 
				
			||||||
 | 
					import { $t } from '#/locales';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { useFormSchema } from '../data';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const emit = defineEmits(['success']);
 | 
				
			||||||
 | 
					const formData = ref<CrmProductCategoryApi.ProductCategory>();
 | 
				
			||||||
 | 
					const getTitle = computed(() => {
 | 
				
			||||||
 | 
					  return formData.value?.id
 | 
				
			||||||
 | 
					    ? $t('ui.actionTitle.edit', ['产品分类'])
 | 
				
			||||||
 | 
					    : $t('ui.actionTitle.create', ['产品分类']);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Form, formApi] = useVbenForm({
 | 
				
			||||||
 | 
					  commonConfig: {
 | 
				
			||||||
 | 
					    componentProps: {
 | 
				
			||||||
 | 
					      class: 'w-full',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    formItemClass: 'col-span-2',
 | 
				
			||||||
 | 
					    labelWidth: 80,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  layout: 'horizontal',
 | 
				
			||||||
 | 
					  schema: useFormSchema(),
 | 
				
			||||||
 | 
					  showDefaultActions: false,
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [Modal, modalApi] = useVbenModal({
 | 
				
			||||||
 | 
					  async onConfirm() {
 | 
				
			||||||
 | 
					    const { valid } = await formApi.validate();
 | 
				
			||||||
 | 
					    if (!valid) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    modalApi.lock();
 | 
				
			||||||
 | 
					    // 提交表单
 | 
				
			||||||
 | 
					    const data =
 | 
				
			||||||
 | 
					      (await formApi.getValues()) as CrmProductCategoryApi.ProductCategory;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await (formData.value?.id
 | 
				
			||||||
 | 
					        ? updateProductCategory(data)
 | 
				
			||||||
 | 
					        : createProductCategory(data));
 | 
				
			||||||
 | 
					      // 关闭并提示
 | 
				
			||||||
 | 
					      await modalApi.close();
 | 
				
			||||||
 | 
					      emit('success');
 | 
				
			||||||
 | 
					      message.success($t('ui.actionMessage.operationSuccess'));
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      modalApi.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  async onOpenChange(isOpen: boolean) {
 | 
				
			||||||
 | 
					    if (!isOpen) {
 | 
				
			||||||
 | 
					      formData.value = undefined;
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // 加载数据
 | 
				
			||||||
 | 
					    let data = modalApi.getData<CrmProductCategoryApi.ProductCategory>();
 | 
				
			||||||
 | 
					    if (!data) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    modalApi.lock();
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      if (data.id) {
 | 
				
			||||||
 | 
					        data = await getProductCategory(data.id as number);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // 设置到 values
 | 
				
			||||||
 | 
					      formData.value = data;
 | 
				
			||||||
 | 
					      await formApi.setValues(data);
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      modalApi.unlock();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <Modal class="w-[600px]" :title="getTitle">
 | 
				
			||||||
 | 
					    <Form class="mx-4" />
 | 
				
			||||||
 | 
					  </Modal>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue