From 20f0ed841546546d94c4ae55355c43cd174b4ce6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 19 Nov 2025 08:12:39 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90ele=E3=80=91=E3=80=90crm?= =?UTF-8?q?=E3=80=91customer=20=E7=9A=84=E8=BF=81=E7=A7=BB=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web-ele/src/router/routes/modules/crm.ts | 18 +- apps/web-ele/src/views/crm/customer/data.ts | 395 ++++++++++++++++++ .../src/views/crm/customer/detail/data.ts | 130 ++++++ .../src/views/crm/customer/detail/index.vue | 312 ++++++++++++++ .../detail/modules/distribute-form.vue | 69 +++ .../crm/customer/detail/modules/info.vue | 38 ++ apps/web-ele/src/views/crm/customer/index.vue | 207 +++++++++ .../views/crm/customer/limitConfig/data.ts | 154 +++++++ .../views/crm/customer/limitConfig/index.vue | 168 ++++++++ .../crm/customer/limitConfig/modules/form.vue | 100 +++++ .../src/views/crm/customer/modules/form.vue | 85 ++++ .../crm/customer/modules/import-form.vue | 87 ++++ .../src/views/crm/customer/pool/data.ts | 161 +++++++ .../src/views/crm/customer/pool/index.vue | 97 +++++ .../src/views/crm/customer/poolConfig/data.ts | 84 ++++ .../views/crm/customer/poolConfig/index.vue | 69 +++ 16 files changed, 2165 insertions(+), 9 deletions(-) create mode 100644 apps/web-ele/src/views/crm/customer/data.ts create mode 100644 apps/web-ele/src/views/crm/customer/detail/data.ts create mode 100644 apps/web-ele/src/views/crm/customer/detail/index.vue create mode 100644 apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue create mode 100644 apps/web-ele/src/views/crm/customer/detail/modules/info.vue create mode 100644 apps/web-ele/src/views/crm/customer/index.vue create mode 100644 apps/web-ele/src/views/crm/customer/limitConfig/data.ts create mode 100644 apps/web-ele/src/views/crm/customer/limitConfig/index.vue create mode 100644 apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue create mode 100644 apps/web-ele/src/views/crm/customer/modules/form.vue create mode 100644 apps/web-ele/src/views/crm/customer/modules/import-form.vue create mode 100644 apps/web-ele/src/views/crm/customer/pool/data.ts create mode 100644 apps/web-ele/src/views/crm/customer/pool/index.vue create mode 100644 apps/web-ele/src/views/crm/customer/poolConfig/data.ts create mode 100644 apps/web-ele/src/views/crm/customer/poolConfig/index.vue diff --git a/apps/web-ele/src/router/routes/modules/crm.ts b/apps/web-ele/src/router/routes/modules/crm.ts index dbf83bc60..13fc8772b 100644 --- a/apps/web-ele/src/router/routes/modules/crm.ts +++ b/apps/web-ele/src/router/routes/modules/crm.ts @@ -20,15 +20,15 @@ const routes: RouteRecordRaw[] = [ }, component: () => import('#/views/crm/clue/detail/index.vue'), }, - // { - // path: 'customer/detail/:id', - // name: 'CrmCustomerDetail', - // meta: { - // title: '客户详情', - // activePath: '/crm/customer', - // }, - // component: () => import('#/views/crm/customer/detail/index.vue'), - // }, + { + path: 'customer/detail/:id', + name: 'CrmCustomerDetail', + meta: { + title: '客户详情', + activePath: '/crm/customer', + }, + component: () => import('#/views/crm/customer/detail/index.vue'), + }, { path: 'business/detail/:id', name: 'CrmBusinessDetail', diff --git a/apps/web-ele/src/views/crm/customer/data.ts b/apps/web-ele/src/views/crm/customer/data.ts new file mode 100644 index 000000000..d7c53c348 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/data.ts @@ -0,0 +1,395 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '@vben/common-ui'; +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { useUserStore } from '@vben/stores'; + +import { getAreaTree } from '#/api/system/area'; +import { getSimpleUserList } from '#/api/system/user'; +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + rules: 'required', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'source', + label: '客户来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), + placeholder: '请选择客户来源', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机', + allowClear: true, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + allowClear: true, + }, + }, + { + fieldName: 'email', + label: '邮箱', + component: 'Input', + componentProps: { + placeholder: '请输入邮箱', + allowClear: true, + }, + }, + { + fieldName: 'wechat', + label: '微信', + component: 'Input', + componentProps: { + placeholder: '请输入微信', + allowClear: true, + }, + }, + { + fieldName: 'qq', + label: 'QQ', + component: 'Input', + componentProps: { + placeholder: '请输入QQ', + allowClear: true, + }, + }, + { + fieldName: 'industryId', + label: '客户行业', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), + placeholder: '请选择客户行业', + allowClear: true, + }, + }, + { + fieldName: 'level', + label: '客户级别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), + placeholder: '请选择客户级别', + allowClear: true, + }, + }, + { + fieldName: 'areaId', + label: '地址', + component: 'ApiTreeSelect', + componentProps: { + api: getAreaTree, + fieldNames: { label: 'name', value: 'id', children: 'children' }, + placeholder: '请选择地址', + allowClear: true, + }, + }, + { + fieldName: 'detailAddress', + label: '详细地址', + component: 'Input', + componentProps: { + placeholder: '请输入详细地址', + allowClear: true, + }, + }, + { + fieldName: 'contactNextTime', + label: '下次联系时间', + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + placeholder: '请选择下次联系时间', + allowClear: true, + }, + }, + { + fieldName: 'remark', + label: '备注', + component: 'Textarea', + componentProps: { + placeholder: '请输入备注', + allowClear: true, + }, + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + componentProps: { + placeholder: '请输入手机号', + allowClear: true, + }, + }, + { + fieldName: 'telephone', + label: '电话', + component: 'Input', + componentProps: { + placeholder: '请输入电话', + allowClear: true, + }, + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + placeholder: ['开始日期', '结束日期'], + allowClear: true, + }, + }, + ]; +} + +/** 导入客户的表单 */ +export function useImportFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + placeholder: '请选择负责人', + allowClear: true, + class: 'w-full', + }, + dependencies: { + triggerFields: ['id'], + disabled: (values) => values.id, + }, + rules: 'required', + }, + { + fieldName: 'file', + label: '客户数据', + component: 'Upload', + rules: 'required', + help: '仅允许导入 xls、xlsx 格式文件', + }, + { + fieldName: 'updateSupport', + label: '是否覆盖', + component: 'Switch', + componentProps: { + activeValue: true, + inactiveValue: false, + }, + rules: z.boolean().default(false), + help: '是否更新已经存在的客户数据', + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'name', + title: '客户名称', + fixed: 'left', + minWidth: 160, + slots: { default: 'name' }, + }, + { + field: 'source', + title: '客户来源', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + field: 'mobile', + title: '手机', + minWidth: 120, + }, + { + field: 'telephone', + title: '电话', + minWidth: 130, + }, + { + field: 'email', + title: '邮箱', + minWidth: 180, + }, + { + field: 'level', + title: '客户级别', + minWidth: 135, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + field: 'industryId', + title: '客户行业', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + field: 'contactNextTime', + title: '下次联系时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'remark', + title: '备注', + minWidth: 200, + }, + { + field: 'lockStatus', + title: '锁定状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'dealStatus', + title: '成交状态', + minWidth: 120, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + field: 'contactLastTime', + title: '最后跟进时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'contactLastContent', + title: '最后跟进记录', + minWidth: 200, + }, + { + field: 'detailAddress', + title: '地址', + minWidth: 180, + }, + { + field: 'poolDay', + title: '距离进入公海天数', + minWidth: 140, + formatter: ({ cellValue }) => + cellValue === null ? '-' : `${cellValue} 天`, + }, + { + field: 'ownerUserName', + title: '负责人', + minWidth: 100, + }, + { + field: 'ownerUserDeptName', + title: '所属部门', + minWidth: 100, + }, + { + field: 'updateTime', + title: '更新时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + minWidth: 180, + }, + { + field: 'creatorName', + title: '创建人', + minWidth: 100, + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/detail/data.ts b/apps/web-ele/src/views/crm/customer/detail/data.ts new file mode 100644 index 000000000..9d55b4077 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/data.ts @@ -0,0 +1,130 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { DescriptionItemSchema } from '#/components/description'; + +import { h } from 'vue'; + +import { DICT_TYPE } from '@vben/constants'; +import { useUserStore } from '@vben/stores'; +import { formatDateTime } from '@vben/utils'; + +import { getSimpleUserList } from '#/api/system/user'; +import { DictTag } from '#/components/dict-tag'; + +/** 分配客户表单 */ +export function useDistributeFormSchema(): VbenFormSchema[] { + const userStore = useUserStore(); + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'ownerUserId', + label: '负责人', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + }, + defaultValue: userStore.userInfo?.id, + rules: 'required', + }, + ]; +} + +/** 详情页的字段 */ +export function useDetailSchema(): DescriptionItemSchema[] { + return [ + { + field: 'level', + label: '客户级别', + render: (val) => + h(DictTag, { type: DICT_TYPE.CRM_CUSTOMER_LEVEL, value: val }), + }, + { + field: 'dealStatus', + label: '成交状态', + render: (val) => (val ? '已成交' : '未成交'), + }, + { + field: 'ownerUserName', + label: '负责人', + }, + { + field: 'createTime', + label: '创建时间', + render: (val) => formatDateTime(val) as string, + }, + ]; +} + +/** 详情页的基础字段 */ +export function useDetailBaseSchema(): DescriptionItemSchema[] { + return [ + { + field: 'name', + label: '客户名称', + }, + { + field: 'source', + label: '客户来源', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_SOURCE, + value: val, + }), + }, + { + field: 'mobile', + label: '手机', + }, + { + field: 'telephone', + label: '电话', + }, + { + field: 'email', + label: '邮箱', + }, + { + field: 'areaName', + label: '地址', + render: (val, data) => { + const areaName = val ?? ''; + const detailAddress = data?.detailAddress ?? ''; + return [areaName, detailAddress].filter(Boolean).join(' '); + }, + }, + { + field: 'qq', + label: 'QQ', + }, + { + field: 'wechat', + label: '微信', + }, + { + field: 'industryId', + label: '客户行业', + render: (val) => + h(DictTag, { + type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY, + value: val, + }), + }, + { + field: 'contactNextTime', + label: '下次联系时间', + render: (val) => formatDateTime(val) as string, + }, + { + field: 'remark', + label: '备注', + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/detail/index.vue b/apps/web-ele/src/views/crm/customer/detail/index.vue new file mode 100644 index 000000000..c5332f3c5 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/index.vue @@ -0,0 +1,312 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue b/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue new file mode 100644 index 000000000..aa7ca2c05 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/modules/distribute-form.vue @@ -0,0 +1,69 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/detail/modules/info.vue b/apps/web-ele/src/views/crm/customer/detail/modules/info.vue new file mode 100644 index 000000000..58102d4a1 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/detail/modules/info.vue @@ -0,0 +1,38 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/index.vue b/apps/web-ele/src/views/crm/customer/index.vue new file mode 100644 index 000000000..52e09ec82 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/index.vue @@ -0,0 +1,207 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/data.ts b/apps/web-ele/src/views/crm/customer/limitConfig/data.ts new file mode 100644 index 000000000..66bff25b1 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/data.ts @@ -0,0 +1,154 @@ +import type { VbenFormSchema } from '@vben/common-ui'; + +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; +import { handleTree } from '@vben/utils'; + +import { LimitConfType } from '#/api/crm/customer/limitConfig'; +import { getSimpleDeptList } from '#/api/system/dept'; +import { getSimpleUserList } from '#/api/system/user'; + +/** 新增/修改的表单 */ +export function useFormSchema(confType: LimitConfType): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'type', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + fieldName: 'userIds', + label: '规则适用人群', + component: 'ApiSelect', + componentProps: { + api: getSimpleUserList, + labelField: 'nickname', + valueField: 'id', + mode: 'multiple', + allowClear: true, + placeholder: '请选择规则适用人群', + }, + }, + { + 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, + }, + }, + { + fieldName: 'maxCount', + label: + confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT + ? '拥有客户数上限' + : '锁定客户数上限', + component: 'InputNumber', + componentProps: { + placeholder: `请输入${ + LimitConfType.CUSTOMER_QUANTITY_LIMIT === confType + ? '拥有客户数上限' + : '锁定客户数上限' + }`, + controlsPosition: 'right', + class: '!w-full', + }, + rules: 'required', + }, + { + fieldName: 'dealCountEnabled', + label: '成交客户是否占用拥有客户数', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING, 'boolean'), + }, + dependencies: { + triggerFields: [''], + show: () => confType === LimitConfType.CUSTOMER_QUANTITY_LIMIT, + }, + defaultValue: false, + }, + ]; +} + +/** 列表的字段 */ +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' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/index.vue b/apps/web-ele/src/views/crm/customer/limitConfig/index.vue new file mode 100644 index 000000000..c745fb7dc --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/index.vue @@ -0,0 +1,168 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue b/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue new file mode 100644 index 000000000..ded5a127d --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/limitConfig/modules/form.vue @@ -0,0 +1,100 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/modules/form.vue b/apps/web-ele/src/views/crm/customer/modules/form.vue new file mode 100644 index 000000000..549adc9e3 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/modules/form.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/modules/import-form.vue b/apps/web-ele/src/views/crm/customer/modules/import-form.vue new file mode 100644 index 000000000..a56968b46 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/modules/import-form.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/pool/data.ts b/apps/web-ele/src/views/crm/customer/pool/data.ts new file mode 100644 index 000000000..d057b67ed --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/pool/data.ts @@ -0,0 +1,161 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { DICT_TYPE } from '@vben/constants'; +import { getDictOptions } from '@vben/hooks'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '客户名称', + component: 'Input', + componentProps: { + placeholder: '请输入客户名称', + allowClear: true, + }, + }, + { + fieldName: 'mobile', + label: '手机', + component: 'Input', + componentProps: { + placeholder: '请输入手机', + allowClear: true, + }, + }, + { + fieldName: 'industryId', + label: '所属行业', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_INDUSTRY, 'number'), + placeholder: '请选择所属行业', + allowClear: true, + }, + }, + { + fieldName: 'level', + label: '客户级别', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_LEVEL, 'number'), + placeholder: '请选择客户级别', + allowClear: true, + }, + }, + { + fieldName: 'source', + label: '客户来源', + component: 'Select', + componentProps: { + options: getDictOptions(DICT_TYPE.CRM_CUSTOMER_SOURCE, 'number'), + placeholder: '请选择客户来源', + allowClear: true, + }, + }, + ]; +} + +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + title: '客户名称', + field: 'name', + minWidth: 160, + fixed: 'left', + slots: { default: 'name' }, + }, + { + title: '客户来源', + field: 'source', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_SOURCE }, + }, + }, + { + title: '手机', + field: 'mobile', + minWidth: 120, + }, + { + title: '电话', + field: 'telephone', + minWidth: 120, + }, + { + title: '邮箱', + field: 'email', + minWidth: 140, + }, + { + title: '客户级别', + field: 'level', + minWidth: 135, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_LEVEL }, + }, + }, + { + title: '客户行业', + field: 'industryId', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.CRM_CUSTOMER_INDUSTRY }, + }, + }, + { + title: '下次联系时间', + field: 'contactNextTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '备注', + field: 'remark', + minWidth: 200, + }, + { + title: '成交状态', + field: 'dealStatus', + minWidth: 80, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.INFRA_BOOLEAN_STRING }, + }, + }, + { + title: '最后跟进时间', + field: 'contactLastTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '最后跟进记录', + field: 'contactLastContent', + minWidth: 200, + }, + { + title: '更新时间', + field: 'updateTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建时间', + field: 'createTime', + minWidth: 180, + formatter: 'formatDateTime', + }, + { + title: '创建人', + field: 'creatorName', + minWidth: 100, + }, + ]; +} diff --git a/apps/web-ele/src/views/crm/customer/pool/index.vue b/apps/web-ele/src/views/crm/customer/pool/index.vue new file mode 100644 index 000000000..abdc0d3ec --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/pool/index.vue @@ -0,0 +1,97 @@ + + + diff --git a/apps/web-ele/src/views/crm/customer/poolConfig/data.ts b/apps/web-ele/src/views/crm/customer/poolConfig/data.ts new file mode 100644 index 000000000..461ef0125 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/poolConfig/data.ts @@ -0,0 +1,84 @@ +import type { VbenFormSchema } from '#/adapter/form'; + +export const schema: VbenFormSchema[] = [ + { + component: 'RadioGroup', + fieldName: 'enabled', + label: '客户公海规则设置', + componentProps: { + options: [ + { label: '开启', value: true }, + { label: '关闭', value: false }, + ], + }, + }, + { + component: 'InputNumber', + fieldName: 'contactExpireDays', + componentProps: { + min: 0, + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + renderComponentContent: () => ({ + addonAfter: () => '天不跟进或', + }), + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + }, + { + component: 'InputNumber', + fieldName: 'dealExpireDays', + renderComponentContent: () => ({ + addonBefore: () => '或', + addonAfter: () => '天未成交', + }), + componentProps: { + min: 0, + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + }, + { + component: 'RadioGroup', + fieldName: 'notifyEnabled', + label: '提前提醒设置', + componentProps: { + options: [ + { label: '开启', value: true }, + { label: '关闭', value: false }, + ], + }, + dependencies: { + triggerFields: ['enabled'], + show: (value) => value.enabled, + }, + defaultValue: false, + }, + { + component: 'InputNumber', + fieldName: 'notifyDays', + componentProps: { + min: 0, + precision: 0, + controlsPosition: 'right', + class: '!w-full', + }, + renderComponentContent: () => ({ + addonBefore: () => '提前', + addonAfter: () => '天提醒', + }), + dependencies: { + triggerFields: ['notifyEnabled'], + show: (value) => value.enabled && value.notifyEnabled, + }, + }, +]; diff --git a/apps/web-ele/src/views/crm/customer/poolConfig/index.vue b/apps/web-ele/src/views/crm/customer/poolConfig/index.vue new file mode 100644 index 000000000..5a40003c6 --- /dev/null +++ b/apps/web-ele/src/views/crm/customer/poolConfig/index.vue @@ -0,0 +1,69 @@ + + +