Compare commits

..

1 Commits

Author SHA1 Message Date
jiangjunhong 6d59888b58 修改配置文件访问域名 2025-04-12 13:01:15 +08:00
54 changed files with 5160 additions and 312 deletions

View File

@ -1,5 +1,5 @@
# 开发环境本地只启动前端项目依赖开发环境后端、APP
NODE_ENV=development
NODE_ENV=production
VITE_DEV=true

View File

@ -30,5 +30,8 @@ VITE_OUT_DIR=dist-prod
# 商城H5会员端域名
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
# 验证码的开关
VITE_APP_CAPTCHA_ENABLE=false
# GoView域名
VITE_GOVIEW_URL='http://127.0.0.1:3000'

View File

@ -7,7 +7,7 @@ ENV TZ=Asia/Shanghai \
LANG=C.UTF-8 \
APP_DIR=/usr/share/nginx/html
COPY dist/. ${APP_DIR}
COPY dist-prod/. ${APP_DIR}
WORKDIR ${APP_DIR}

View File

@ -3,8 +3,8 @@ import request from '@/config/axios'
// 跟进标签 VO
export interface FollowLabelVO {
id: number // ID
followLabel: string // 跟进标签
isOpen: number // 是否开启0关闭1开启
name: string // 跟进标签
status: number // 是否开启0关闭1开启
sort: number // 排序
}

View File

@ -3,11 +3,9 @@ import request from '@/config/axios'
// 重要程度 VO
export interface ImportLevelVO {
id: number // ID
importLevel: string // 重要程度
isOpen: number // 是否开启0关闭1开启
name: string // 重要程度
status: number // 是否开启0关闭1开启
sort: number // 排序
deleter: string // 删除者
deleteTime: Date // 删除时间
}
// 重要程度 API
@ -17,6 +15,11 @@ export const ImportLevelApi = {
return await request.get({ url: `/crm/import-level/page`, params })
},
// 查询重要程度列表
getImportLevelList: async (params: any) => {
return await request.get({ url: `/crm/import-level/list`,params })
},
// 查询重要程度详情
getImportLevel: async (id: number) => {
return await request.get({ url: `/crm/import-level/get?id=` + id })
@ -35,10 +38,13 @@ export const ImportLevelApi = {
// 删除重要程度
deleteImportLevel: async (id: number) => {
return await request.delete({ url: `/crm/import-level/delete?id=` + id })
},
}
}
// 修改开启状态
updateOpenStatus: async (id: number) => {
return await request.put({ url: `/crm/import-level/updateOpenStatusById?id=` + id })
}
}

View File

@ -4,7 +4,7 @@ import request from '@/config/axios'
export interface ChannelVO {
id:number //渠道编号
type: string // 类型1:线索渠道)
channel: string // 渠道名称
name: string // 渠道名称
remark: string // 备注
}

View File

@ -2,8 +2,8 @@ import request from '@/config/axios'
// 客户标签 VO
export interface CustomerLabelVO {
customerLabel: string // 客户标签
isOpen: number // 是否开启0关闭1开启
name: string // 客户标签
status: number // 是否开启0关闭1开启
sort: number // 排序
}

View File

@ -2,8 +2,9 @@ import request from '@/config/axios'
// 客户来源 VO
export interface CustomerSourceVO {
customerSource: string // 客户来源
isOpen: number // 是否开启0关闭1开启
id:number
name: string // 客户来源
status: number // 是否开启
sort: number // 排序
parentId:number //父级ID
}

View File

@ -3,8 +3,8 @@ import request from '@/config/axios'
// 客户类型 VO
export interface CustomerTypeVO {
id: number // ID
customerType: string // 客户类型
isOpen: number // 是否开启0关闭1开启
name: string // 客户类型
status: number // 是否开启
sort: number // 排序
parentId: number // 父ID
}

View File

@ -3,8 +3,8 @@ import request from '@/config/axios'
// 跟进状态 VO
export interface FollowStatusVO {
id: number // ID
followStatus: string // 跟进状态
isOpen: number // 是否开启0关闭1开启
name: string // 跟进状态
status: number // 是否开启
sort: number // 排序
}
@ -15,6 +15,11 @@ export const FollowStatusApi = {
return await request.get({ url: `/crm/follow-status/page`, params })
},
// 查询跟进状态分页
getFollowStatusList: async (params: any) => {
return await request.get({ url: `/crm/follow-status/list`, params })
},
// 查询跟进状态详情
getFollowStatus: async (id: number) => {
return await request.get({ url: `/crm/follow-status/get?id=` + id })

View File

@ -0,0 +1,45 @@
import request from '@/config/axios'
// 公海管理 VO
export interface OpenSeaVO {
id: number // id
openSea: string // 公海名称
type: number // 公海类型1:内置2:自定义)
depIds: string // 适用部门112233
remark: string // 备注
sort: number // 排序
isOpen: number // 是否开启0:关闭1:开启)
}
// 公海管理 API
export const OpenSeaApi = {
// 查询公海管理分页
getOpenSeaPage: async (params: any) => {
return await request.get({ url: `/crm/open-sea/page`, params })
},
// 查询公海管理详情
getOpenSea: async (id: number) => {
return await request.get({ url: `/crm/open-sea/get?id=` + id })
},
// 新增公海管理
createOpenSea: async (data: OpenSeaVO) => {
return await request.post({ url: `/crm/open-sea/create`, data })
},
// 修改公海管理
updateOpenSea: async (data: OpenSeaVO) => {
return await request.put({ url: `/crm/open-sea/update`, data })
},
// 删除公海管理
deleteOpenSea: async (id: number) => {
return await request.delete({ url: `/crm/open-sea/delete?id=` + id })
},
// 修改开启状态
updateOpenStatus: async (id: number) => {
return await request.put({ url: `/crm/open-sea/updateOpenStatusById?id=` + id })
}
}

View File

@ -0,0 +1,63 @@
import request from '@/config/axios'
// 客户信息 VO
export interface CustomerInforVO {
id: number // 客户ID
customerName: string // 客户姓名
expectAmount: string // 期望金额
age: number // 年龄
sex: number // 性别0:未知 1:男生2:女生)
mobile: string // 手机号码
address: string // 居住地址
haveCar: number // 是否有车(0:没车1:有车)
haveHouse: number // 是否有房0:没房1:有房)
haveProvidentFund: number // 是否有公积金0:没公积金1有公积金
haveSocialSecurity: number // 是否有社保0:没社保1:有社保)
haveGuaranteeSlip: number // 是否有保单0:没保单1:有保单)
customerSourceId: number // 客户来源ID
customerTypeId: number // 客户类型ID
remark: string // 客户资料
importLevelId: number // 重要程度ID
followStatusId: number // 跟进状态id
ownerUserId: number // 负责人ID
ownerTime: Date // 成为负责人时间
depId: number // 部门ID
contactLastTime: Date // 最后跟进时间
contactLastContent: string // 最后跟进内容
contactNextTime: Date // 下次联系时间
lockStatus: number // 锁定状态0:未锁1:锁定)
openSeaId: number // 公海ID
}
// 客户信息 API
export const CustomerInforApi = {
// 查询客户信息分页
getCustomerInforPage: async (params: any) => {
return await request.get({ url: `/crm/customer-infor/page`, params })
},
// 查询客户信息详情
getCustomerInfor: async (id: number) => {
return await request.get({ url: `/crm/customer-infor/get?id=` + id })
},
// 新增客户信息
createCustomerInfor: async (data: CustomerInforVO) => {
return await request.post({ url: `/crm/customer-infor/create`, data })
},
// 修改客户信息
updateCustomerInfor: async (data: CustomerInforVO) => {
return await request.put({ url: `/crm/customer-infor/update`, data })
},
// 删除客户信息
deleteCustomerInfor: async (id: number) => {
return await request.delete({ url: `/crm/customer-infor/delete?id=` + id })
},
// 导出客户信息 Excel
exportCustomerInfor: async (params) => {
return await request.download({ url: `/crm/customer-infor/export-excel`, params })
}
}

View File

@ -0,0 +1,53 @@
import request from '@/config/axios'
// 导入详情 VO
export interface UploadDetailVO {
id: number // 客户ID
uploadId: number // 上传记录ID
name: string // 客户姓名
expectAmount: string // 期望金额
age: number // 年龄
sex: number // 性别0:未知1:男生2:女生)
mobile: string // 手机号码
address: string // 居住地址
haveCar: number // 是否有车(0:没车1:有车)
haveHouse: number // 是否有房0:没房1:有房)
haveProvidentFund: number // 是否有公积金0:没公积金1有公积金
haveSocialSecurity: number // 是否有社保0:没社保1:有社保)
haveGuaranteeSlip: number // 是否有保单0:没保单1:有保单)
remark: string // 备注信息
isRepeat: number // 是否重复0:否1:是)
}
// 导入详情 API
export const UploadDetailApi = {
// 查询导入详情分页
getUploadDetailPage: async (params: any) => {
return await request.get({ url: `/crm/upload-detail/page`, params })
},
// 查询导入详情详情
getUploadDetail: async (id: number) => {
return await request.get({ url: `/crm/upload-detail/get?id=` + id })
},
// 新增导入详情
createUploadDetail: async (data: UploadDetailVO) => {
return await request.post({ url: `/crm/upload-detail/create`, data })
},
// 修改导入详情
updateUploadDetail: async (data: UploadDetailVO) => {
return await request.put({ url: `/crm/upload-detail/update`, data })
},
// 删除导入详情
deleteUploadDetail: async (id: number) => {
return await request.delete({ url: `/crm/upload-detail/delete?id=` + id })
},
// 导出导入详情 Excel
exportUploadDetail: async (params) => {
return await request.download({ url: `/crm/upload-detail/export-excel`, params })
}
}

View File

@ -0,0 +1,48 @@
import request from '@/config/axios'
// 导入记录 VO
export interface UploadRecordVO {
id: number // 唯一标识
fileName: string // 上传文件名称
fileId: string // 上传文件编号
totalCount: number // 总数
repeatCount: number // 重复数量
newCount: number // 新增数量
isCover: number // 是否覆盖(0:不覆盖1覆盖)
openSeaId: number // 公海ID
customerSourceId: number // 数据来源ID
creater: string // 创建者
}
// 导入记录 API
export const UploadRecordApi = {
// 查询导入记录分页
getUuploadRecordPage: async (params: any) => {
return await request.get({ url: `/crm/upload-record/page`, params })
},
// 查询导入记录详情
getUuploadRecord: async (id: number) => {
return await request.get({ url: `/crm/upload-record/get?id=` + id })
},
// 新增导入记录
createUuploadRecord: async (data: UploadRecordVO) => {
return await request.post({ url: `/crm/upload-record/create`, data })
},
// 修改导入记录
updateUuploadRecord: async (data: UploadRecordVO) => {
return await request.put({ url: `/crm/upload-record/update`, data })
},
// 删除导入记录
deleteUuploadRecord: async (id: number) => {
return await request.delete({ url: `/crm/upload-record/delete?id=` + id })
},
// 导出导入记录 Excel
exportUuploadRecord: async (params) => {
return await request.download({ url: `/crm/upload-record/export-excel`, params })
}
}

View File

@ -0,0 +1,41 @@
import request from '@/config/axios'
// 跟进记录 VO
export interface FollwRecordVO {
id: number // 唯一标识
customerId: number // 客户ID
content: string // 跟进内容
}
// 跟进记录 API
export const FollwRecordApi = {
// 查询跟进记录分页
getFollwRecordPage: async (params: any) => {
return await request.get({ url: `/crm/follw-record/page`, params })
},
// 查询跟进记录详情
getFollwRecord: async (id: number) => {
return await request.get({ url: `/crm/follw-record/get?id=` + id })
},
// 新增跟进记录
createFollwRecord: async (data: FollwRecordVO) => {
return await request.post({ url: `/crm/follw-record/create`, data })
},
// 修改跟进记录
updateFollwRecord: async (data: FollwRecordVO) => {
return await request.put({ url: `/crm/follw-record/update`, data })
},
// 删除跟进记录
deleteFollwRecord: async (id: number) => {
return await request.delete({ url: `/crm/follw-record/delete?id=` + id })
},
// 导出跟进记录 Excel
exportFollwRecord: async (params) => {
return await request.download({ url: `/crm/follw-record/export-excel`, params })
}
}

View File

@ -23,8 +23,13 @@ export const getUserPage = (params: PageParam) => {
}
// 查询所有用户列表
export const getAllUser = () => {
return request.get({ url: '/system/user/all' })
export const getAllUser = () => {
return request.get({ url: '/system/user/simple-list' })
}
// 查询所有用户列表
export const getSimpleUsertList = () => {
return request.get({ url: '/system/user/simple-list' })
}
// 查询用户详情

View File

@ -4,8 +4,8 @@
v-show="total > 0"
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:background="true"
:page-sizes="[10, 20, 30, 50, 100]"
:background="true"
:page-sizes="[10,15, 20, 30, 50, 100]"
:pager-count="pagerCount"
:total="total"
:small="isSmall"

View File

@ -44,6 +44,7 @@ export default defineComponent({
const routers = computed(() =>
unref(layout) === 'cutMenu' ? permissionStore.getMenuTabRouters : permissionStore.getRouters
)
const collapse = computed(() => appStore.getCollapse)
@ -59,6 +60,7 @@ export default defineComponent({
})
const menuSelect = (index: string) => {
if (props.menuSelect) {
props.menuSelect(index)
}

View File

@ -7,6 +7,9 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
'.DS_Store': typeof import('./../../.DS_Store')['default']
'.gitignore': typeof import('./../../.gitignore')['default']
Allcustomer: typeof import('./../views/crm/customer/customerinfor/allcustomer/index.vue')['default']
AppLinkInput: typeof import('./../components/AppLinkInput/index.vue')['default']
AppLinkSelectDialog: typeof import('./../components/AppLinkInput/AppLinkSelectDialog.vue')['default']
'AutoComponents.d': typeof import('./auto-components.d.ts')['default']
@ -15,6 +18,14 @@ declare module 'vue' {
BoundaryEventTimer: typeof import('./../components/bpmnProcessDesigner/package/penal/custom-config/components/BoundaryEventTimer.vue')['default']
CallActivity: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/CallActivity.vue')['default']
CardTitle: typeof import('./../components/Card/src/CardTitle.vue')['default']
Channel: typeof import('./../api/crm/config/channel/index.ts')['default']
ChannelForm: typeof import('./../views/crm/config/channel/ChannelForm.vue')['default']
Cluedatacontrast: typeof import('../api/crm/clue/datacontrast')['default']
ClueDataContrastForm: typeof import('./../views/crm/thridDzta/datacontrast/ClueDataContrastForm.vue')['default']
Cluerawdata: typeof import('../api/crm/clue/rawdata')['default']
ClueRawDataForm: typeof import('./../views/crm/thridDzta/rawdata/ClueRawDataForm.vue')['default']
Cluesource: typeof import('../api/crm/clue/source')['default']
ClueSourceForm: typeof import('./../views/crm/thridDzta/source/ClueSourceForm.vue')['default']
ColorInput: typeof import('./../components/ColorInput/index.vue')['default']
ComponentContainer: typeof import('./../components/DiyEditor/components/ComponentContainer.vue')['default']
ComponentContainerProperty: typeof import('./../components/DiyEditor/components/ComponentContainerProperty.vue')['default']
@ -24,14 +35,26 @@ declare module 'vue' {
ContentDetailWrap: typeof import('./../components/ContentDetailWrap/src/ContentDetailWrap.vue')['default']
ContentWrap: typeof import('./../components/ContentWrap/src/ContentWrap.vue')['default']
CopperModal: typeof import('./../components/Cropper/src/CopperModal.vue')['default']
copy: typeof import('./../views/crm/config/opensea/OpenSeaForm copy.vue')['default']
CopyTaskNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue')['default']
CopyTaskNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue')['default']
CountTo: typeof import('./../components/CountTo/src/CountTo.vue')['default']
Crontab: typeof import('./../components/Crontab/src/Crontab.vue')['default']
Cropper: typeof import('./../components/Cropper/src/Cropper.vue')['default']
CropperAvatar: typeof import('./../components/Cropper/src/CropperAvatar.vue')['default']
Customerinfor: typeof import('./../api/crm/customer/customerinfor/index.ts')['default']
CustomerInforForm: typeof import('./../views/crm/customer/customerinfor/openseacustomer/CustomerInforForm.vue')['default']
Customerlabel: typeof import('./../api/crm/config/customerlabel/index.ts')['default']
CustomerLabelForm: typeof import('./../views/crm/config/customerlabel/CustomerLabelForm.vue')['default']
Customersource: typeof import('./../api/crm/config/customersource/index.ts')['default']
CustomerSourceForm: typeof import('./../views/crm/config/customersource/CustomerSourceForm.vue')['default']
Customertype: typeof import('./../api/crm/config/customertype/index.ts')['default']
CustomerTypeForm: typeof import('./../views/crm/config/customertype/CustomerTypeForm.vue')['default']
Datacontrast: typeof import('./../api/crm/thirdData/datacontrast/index.ts')['default']
DataContrastForm: typeof import('./../views/crm/thirdData/datacontrast/DataContrastForm.vue')['default']
DelayTimerNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue')['default']
DelayTimerNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue')['default']
Depcustomer: typeof import('./../views/crm/customer/customerinfor/depcustomer/index.vue')['default']
Descriptions: typeof import('./../components/Descriptions/src/Descriptions.vue')['default']
DescriptionsItemLabel: typeof import('./../components/Descriptions/src/DescriptionsItemLabel.vue')['default']
Dialog: typeof import('./../components/Dialog/src/Dialog.vue')['default']
@ -50,8 +73,6 @@ declare module 'vue' {
ElButton: typeof import('element-plus/es')['ElButton']
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
ElCard: typeof import('element-plus/es')['ElCard']
ElCarousel: typeof import('element-plus/es')['ElCarousel']
ElCarouselItem: typeof import('element-plus/es')['ElCarouselItem']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
@ -59,7 +80,6 @@ declare module 'vue' {
ElCollapse: typeof import('element-plus/es')['ElCollapse']
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElContainer: typeof import('element-plus/es')['ElContainer']
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
@ -96,13 +116,10 @@ declare module 'vue' {
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRate: typeof import('element-plus/es')['ElRate']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSegmented: typeof import('element-plus/es')['ElSegmented']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
ElSlider: typeof import('element-plus/es')['ElSlider']
ElSpace: typeof import('element-plus/es')['ElSpace']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
@ -114,8 +131,6 @@ declare module 'vue' {
ElText: typeof import('element-plus/es')['ElText']
ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTransfer: typeof import('element-plus/es')['ElTransfer']
ElTree: typeof import('element-plus/es')['ElTree']
@ -124,20 +139,34 @@ declare module 'vue' {
EndEventNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue')['default']
Error: typeof import('./../components/Error/src/Error.vue')['default']
ExclusiveNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue')['default']
FileForm: typeof import('./../views/crm/customer/uploadrecord/FileForm.vue')['default']
FlowCondition: typeof import('./../components/bpmnProcessDesigner/package/penal/flow-condition/FlowCondition.vue')['default']
Followlabel: typeof import('./../api/crm/config/Followlabel/index.ts')['default']
FollowLabelForm: typeof import('./../views/crm/config/Followlabel/FollowLabelForm.vue')['default']
Followstatus: typeof import('./../api/crm/config/followstatus/index.ts')['default']
FollowStatusForm: typeof import('./../views/crm/config/followstatus/FollowStatusForm.vue')['default']
Follwrecord: typeof import('./../api/crm/follw/follwrecord/index.ts')['default']
FollwRecordForm: typeof import('./../views/crm/follw/follwrecord/FollwRecordForm.vue')['default']
Form: typeof import('./../components/Form/src/Form.vue')['default']
Highlight: typeof import('./../components/Highlight/src/Highlight.vue')['default']
Icon: typeof import('./../components/Icon/src/Icon.vue')['default']
IconSelect: typeof import('./../components/Icon/src/IconSelect.vue')['default']
IFrame: typeof import('./../components/IFrame/src/IFrame.vue')['default']
ImageViewer: typeof import('./../components/ImageViewer/src/ImageViewer.vue')['default']
Importlevel: typeof import('./../api/crm/config/Importlevel/index.ts')['default']
ImportLevelForm: typeof import('./../views/crm/config/Importlevel/ImportLevelForm.vue')['default']
InclusiveNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue')['default']
Infotip: typeof import('./../components/Infotip/src/Infotip.vue')['default']
InputPassword: typeof import('./../components/InputPassword/src/InputPassword.vue')['default']
InputWithColor: typeof import('./../components/InputWithColor/index.vue')['default']
Label: typeof import('./../api/crm/config/label/index.ts')['default']
MagicCubeEditor: typeof import('./../components/MagicCubeEditor/index.vue')['default']
MarkdownView: typeof import('./../components/MarkdownView/index.vue')['default']
Mycustomer: typeof import('./../views/crm/customer/customerinfor/mycustomer/index.vue')['default']
NodeHandler: typeof import('./../components/SimpleProcessDesignerV2/src/NodeHandler.vue')['default']
Opensea: typeof import('./../api/crm/config/opensea/index.ts')['default']
Openseacustomer: typeof import('./../views/crm/customer/customerinfor/openseacustomer/index.vue')['default']
OpenSeaForm: typeof import('./../views/crm/config/opensea/OpenSeaForm.vue')['default']
OperateLogV2: typeof import('./../components/OperateLogV2/src/OperateLogV2.vue')['default']
Pagination: typeof import('./../components/Pagination/index.vue')['default']
ParallelNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue')['default']
@ -149,6 +178,8 @@ declare module 'vue' {
ProcessViewer: typeof import('./../components/bpmnProcessDesigner/package/designer/ProcessViewer.vue')['default']
PropertiesPanel: typeof import('./../components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue')['default']
Qrcode: typeof import('./../components/Qrcode/src/Qrcode.vue')['default']
Rawdata: typeof import('./../api/crm/thirdData/rawdata/index.ts')['default']
RawDataForm: typeof import('./../views/crm/thirdData/rawdata/RawDataForm.vue')['default']
ReceiveTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/ReceiveTask.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterSearch: typeof import('./../components/RouterSearch/index.vue')['default']
@ -161,6 +192,7 @@ declare module 'vue' {
SimpleProcessDesigner: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue')['default']
SimpleProcessModel: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue')['default']
SimpleProcessViewer: typeof import('./../components/SimpleProcessDesignerV2/src/SimpleProcessViewer.vue')['default']
Source: typeof import('./../views/crm/thridDzta/source/index.vue')['default']
StartUserNode: typeof import('./../components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue')['default']
StartUserNodeConfig: typeof import('./../components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue')['default']
Sticky: typeof import('./../components/Sticky/src/Sticky.vue')['default']
@ -168,9 +200,13 @@ declare module 'vue' {
Table: typeof import('./../components/Table/src/Table.vue')['default']
TableSelectForm: typeof import('./../components/Table/src/TableSelectForm.vue')['default']
Tooltip: typeof import('./../components/Tooltip/src/Tooltip.vue')['default']
Uploaddetail: typeof import('./../api/crm/customer/uploaddetail/index.ts')['default']
UploadDetailForm: typeof import('./../views/crm/customer/uploaddetail/UploadDetailForm.vue')['default']
UploadFile: typeof import('./../components/UploadFile/src/UploadFile.vue')['default']
UploadImg: typeof import('./../components/UploadFile/src/UploadImg.vue')['default']
UploadImgs: typeof import('./../components/UploadFile/src/UploadImgs.vue')['default']
Uploadrecord: typeof import('./../api/crm/customer/uploadrecord/index.ts')['default']
UploadRecordForm: typeof import('./../views/crm/customer/uploadrecord/UploadRecordForm.vue')['default']
UserSelectForm: typeof import('./../components/UserSelectForm/index.vue')['default']
UserTask: typeof import('./../components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue')['default']
UserTaskCustomConfig: typeof import('./../components/bpmnProcessDesigner/package/penal/custom-config/components/UserTaskCustomConfig.vue')['default']

View File

@ -35,6 +35,14 @@ export const SystemRoleTypeEnum = {
CUSTOM: 2 // 自定义角色
}
/**
*
*/
export const CrmOpenSeaTypeEnum = {
SYSTEM: 1, // 内置角色
CUSTOM: 2 // 自定义角色
}
/**
*
*/

View File

@ -110,9 +110,11 @@ export const getDictLabel = (dictType: string, value: any): string => {
export enum DICT_TYPE {
USER_TYPE = 'user_type',
COMMON_STATUS = 'common_status',
COMMON_HAVE_STATUS = 'common_have_status',
TERMINAL = 'terminal', // 终端
DATE_INTERVAL = 'date_interval', // 数据间隔
// ========== SYSTEM 模块 ==========
SYSTEM_USER_SEX = 'system_user_sex',
SYSTEM_MENU_TYPE = 'system_menu_type',
@ -213,6 +215,13 @@ export enum DICT_TYPE {
CRM_PRODUCT_UNIT = 'crm_product_unit', // CRM 产品单位
CRM_FOLLOW_UP_TYPE = 'crm_follow_up_type', // CRM 跟进方式
// ========== CRM - 客户管理模块 ==========
CRM_OPEN_SEA_TYPE = 'crm_open_sea_type', // CRM 公海类型
CRM_CHANNEL_TYPE = 'crm_channel_type', // CRM 渠道类型
// ========== ERP - 企业资源计划模块 ==========
ERP_AUDIT_STATUS = 'erp_audit_status', // ERP 审批状态
ERP_STOCK_RECORD_BIZ_TYPE = 'erp_stock_record_biz_type', // 库存明细的业务类型

View File

@ -401,3 +401,32 @@ export const treeToString = (tree: any[], nodeId) => {
}
return str
}
export const buildTree = (data) =>{
const map = {}; // 缓存节点
const tree = []; // 最终树形结果
// 第一遍遍历:初始化节点映射
data.forEach(item => {
map[item.id] = {
value: item.id,
label: item.name,
children: []
};
});
// 第二遍遍历:构建层级关系
data.forEach(item => {
const node = map[item.id] ;
if (item.parentId === 0) {
tree.push(node);
} else {
const parent = map[item.parentId];
if (parent) {
parent.children.push(node);
}
}
});
return tree;
}

View File

@ -7,12 +7,28 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="跟进标签" prop="followLabel">
<el-input v-model="formData.followLabel" placeholder="请输入跟进标签" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
<el-form-item label="跟进标签" prop="name">
<el-input v-model="formData.name" placeholder="请输入跟进标签" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
@ -21,6 +37,8 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { FollowLabelApi, FollowLabelVO } from '@/api/crm/config/Followlabel'
/** 跟进标签 表单 */
@ -35,12 +53,12 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
followLabel: undefined,
isOpen: undefined as number | undefined,
name: undefined,
status: undefined as number | undefined,
sort: undefined
})
const formRules = reactive({
followLabel: [{ required: true, message: '跟进标签不能为空', trigger: 'blur' }],
name: [{ required: true, message: '跟进标签不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
@ -91,8 +109,8 @@ const submitForm = async () => {
const resetForm = () => {
formData.value = {
id: 0,
followLabel: undefined,
isOpen: 1,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined
}
formRef.value?.resetFields()

View File

@ -8,26 +8,24 @@
:inline="true"
label-width="68px"
>
<el-form-item label="跟进标签" prop="followLabel">
<el-form-item label="跟进标签" prop="name">
<el-input
v-model="queryParams.followLabel"
v-model="queryParams.name"
placeholder="请输入跟进标签"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@ -47,15 +45,12 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="left" prop="sort" type="index" width="60px"/>
<el-table-column label="跟进标签" align="left" prop="followLabel" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px" />
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="序号" align="center" prop="sort" type="index" width="60px"/>
<el-table-column label="跟进标签" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="isOpen" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160px">
@ -93,6 +88,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { FollowLabelApi, FollowLabelVO } from '@/api/crm/config/Followlabel'
import FollowLabelForm from './FollowLabelForm.vue'
@ -107,9 +103,9 @@ const list = ref<FollowLabelVO[]>([]) // 列表的数据
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
followLabel: undefined,
isOpen: undefined,
pageSize: 15,
name: undefined,
status: undefined,
sort: undefined
})
const queryFormRef = ref() //
@ -157,12 +153,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await FollowLabelApi.updateOpenStatus(id)
} catch {}
}
/** 初始化 **/
onMounted(() => {

View File

@ -7,22 +7,40 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="重要程度" prop="importLevel">
<el-input v-model="formData.importLevel" placeholder="请输入重要程度" />
<el-form-item label="重要程度" prop="name">
<el-input v-model="formData.name" placeholder="请输入重要程度" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { ImportLevelApi, ImportLevelVO } from '@/api/crm/config/Importlevel'
/** 重要程度 表单 */
@ -37,12 +55,12 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
importLevel: undefined,
isOpen: undefined as number | undefined,
sort: undefined,
name: undefined,
status: undefined as number | undefined,
sort: undefined,
})
const formRules = reactive({
importLevel: [{ required: true, message: '重要程度不能为空', trigger: 'blur' }],
name: [{ required: true, message: '重要程度不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
@ -93,8 +111,8 @@ const submitForm = async () => {
const resetForm = () => {
formData.value = {
id: 0,
importLevel: undefined,
isOpen: 1,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined,
}
formRef.value?.resetFields()

View File

@ -8,26 +8,24 @@
:inline="true"
label-width="68px"
>
<el-form-item label="重要程度" prop="importLevel">
<el-form-item label="重要程度" prop="name">
<el-input
v-model="queryParams.importLevel"
v-model="queryParams.name"
placeholder="请输入重要程度"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@ -48,16 +46,13 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="left" prop="sort" type="index" width="60px"/>
<el-table-column label="重要程度" align="left" prop="importLevel" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px" />
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="重要程度" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
</el-table-column>
<el-table-column label="操作" align="center" width="160px">
<template #default="scope">
<el-button
@ -93,6 +88,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { ImportLevelApi, ImportLevelVO } from '@/api/crm/config/Importlevel'
import ImportLevelForm from './ImportLevelForm.vue'
@ -107,9 +103,9 @@ const list = ref<ImportLevelVO[]>([]) // 列表的数据
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
importLevel: undefined,
isOpen: undefined,
pageSize: 15,
name: undefined,
status: undefined,
})
const queryFormRef = ref() //
@ -156,12 +152,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await ImportLevelApi.updateOpenStatus(id)
} catch {}
}
/** 初始化 **/
onMounted(() => {

View File

@ -6,14 +6,19 @@
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
>
<el-form-item label="类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择类型">
<el-option label="数据" value="1" />
</el-select>
<el-select v-model="formData.type" placeholder="请选择" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_CHANNEL_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="渠道名称" prop="channel">
<el-input v-model="formData.channel" placeholder="请输入渠道名称" />
<el-form-item label="渠道名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入渠道名称" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
@ -26,6 +31,7 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { ChannelApi, ChannelVO } from '@/api/crm/config/channel'
/** 渠道管理 表单 */
@ -41,11 +47,11 @@ const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
id: undefined as number | undefined,
type: undefined,
channel: undefined,
name: undefined,
remark: undefined
})
const formRules = reactive({
channel: [{ required: true, message: '渠道名称不能为空', trigger: 'blur' }],
name: [{ required: true, message: '渠道名称不能为空', trigger: 'blur' }],
type: [{ required: true, message: '请选择渠道类型',trigger: 'change',},],
})
const formRef = ref() // Ref
@ -97,7 +103,7 @@ const resetForm = () => {
formData.value = {
id:0,
type: undefined,
channel: undefined,
name: undefined,
remark: undefined
}
formRef.value?.resetFields()

View File

@ -9,18 +9,18 @@
label-width="68px"
>
<el-form-item label="渠道类型" prop="type">
<el-select
v-model="queryParams.type"
placeholder="请选择类型"
clearable
class="!w-240px"
>
<el-option label="数据" value="1" />
</el-select>
<el-select v-model="queryParams.type" placeholder="请选择" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_CHANNEL_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="渠道名称" prop="channel">
<el-form-item label="渠道名称" prop="name">
<el-input
v-model="queryParams.channel"
v-model="queryParams.name"
placeholder="请输入渠道名称"
clearable
class="!w-240px"
@ -45,8 +45,12 @@
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" width="60" type="index" />
<el-table-column label="渠道类型" align="left" width="120" prop="type" />
<el-table-column label="渠道名称" align="left" width="120" prop="channel" />
<el-table-column label="渠道类型" align="left" width="120" prop="type" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CHANNEL_TYPE" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="渠道名称" align="left" width="120" prop="name" />
<el-table-column label="备注" align="left" min-width="120" prop="remark" />
<el-table-column label="操作" align="left" width="120px">
<template #default="scope">
@ -83,6 +87,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { ChannelApi, ChannelVO } from '@/api/crm/config/channel'
import ChannelForm from './ChannelForm.vue'
@ -97,9 +102,9 @@ const list = ref<ChannelVO[]>([]) // 列表的数据
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
pageSize: 15,
type: undefined,
channel: undefined
name: undefined
})
const queryFormRef = ref() //

View File

@ -7,11 +7,27 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户标签" prop="customerLabel">
<el-input v-model="formData.customerLabel" placeholder="请输入客户标签" />
<el-form-item label="客户标签" prop="name">
<el-input v-model="formData.name" placeholder="请输入客户标签" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
@ -21,6 +37,8 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { CustomerLabelApi, CustomerLabelVO } from '@/api/crm/config/customerlabel'
/** 客户标签 表单 */
@ -35,12 +53,12 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id:undefined as number | undefined,
customerLabel: undefined,
isOpen: undefined as number | undefined,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined
})
const formRules = reactive({
customerLabel: [{ required: true, message: '客户标签不能为空', trigger: 'blur' }],
name: [{ required: true, message: '客户标签不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
@ -91,8 +109,8 @@ const submitForm = async () => {
const resetForm = () => {
formData.value = {
id:0,
customerLabel: undefined,
isOpen: 1,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined
}
formRef.value?.resetFields()

View File

@ -8,26 +8,24 @@
:inline="true"
label-width="68px"
>
<el-form-item label="客户标签" prop="customerLabel">
<el-form-item label="客户标签" prop="name">
<el-input
v-model="queryParams.customerLabel"
v-model="queryParams.name"
placeholder="请输入客户标签"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@ -48,18 +46,15 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="left" prop="sort" type="index" width="60px"/>
<el-table-column label="客户标签" align="left" prop="customerLabel" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px" />
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="序号" align="center" prop="sort" type="index" width="60px"/>
<el-table-column label="客户标签" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="left" width="160px">
<el-table-column label="操作" align="center" width="160px">
<template #default="scope">
<el-button
link
@ -94,6 +89,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CustomerLabelApi, CustomerLabelVO } from '@/api/crm/config/customerlabel'
import CustomerLabelForm from './CustomerLabelForm.vue'
@ -108,9 +104,9 @@ const list = ref<CustomerLabelVO[]>([]) // 列表的数据
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
customerLabel: undefined,
isOpen: undefined
pageSize: 15,
name: undefined,
status: undefined
})
const queryFormRef = ref() //
@ -130,7 +126,7 @@ const getList = async () => {
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
}
/** 重置按钮操作 */
const resetQuery = () => {
@ -157,12 +153,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await CustomerLabelApi.updateOpenStatus(id)
} catch {}
}
/** 初始化 **/

View File

@ -7,11 +7,27 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户来源" prop="customerSource">
<el-input v-model="formData.customerSource" placeholder="请输入客户来源" />
<el-form-item label="客户来源" prop="name">
<el-input v-model="formData.name" placeholder="请输入客户来源" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" type="number" placeholder="请输入排序" />
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
@ -22,6 +38,8 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { CustomerSourceApi, CustomerSourceVO } from '@/api/crm/config/customersource'
/** 客户来源 表单 */
defineOptions({ name: 'CustomerSourceForm' })
@ -35,14 +53,14 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id:undefined as number | undefined,
customerSource: undefined,
name: undefined,
sort: undefined,
parentId:undefined as number | undefined,
isOpen:undefined as number | undefined,
status: CommonStatusEnum.ENABLE,
})
const formRules = reactive({
customerSource: [{ required: true, message: '客户来源不能为空', trigger: 'blur' }],
name: [{ required: true, message: '客户来源不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
@ -98,10 +116,10 @@ const submitForm = async () => {
const resetForm = (id:number) => {
formData.value = {
id:0,
customerSource: undefined,
name: undefined,
sort: undefined,
parentId:id?id:0,
isOpen:1
status: CommonStatusEnum.ENABLE
}
formRef.value?.resetFields()
}

View File

@ -8,24 +8,23 @@
:inline="true"
label-width="68px"
>
<el-form-item label="客户来源" prop="customerSource">
<el-form-item label="客户来源" prop="name">
<el-input
v-model="queryParams.customerSource"
v-model="queryParams.name"
placeholder="请输入客户来源"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@ -57,17 +56,14 @@
v-if="refreshTable"
>
<el-table-column label="序号" align="center" type="index" width="60px" />
<el-table-column label="客户来源" align="left" prop="customerSource" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px"/>
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="客户来源" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
</el-table-column>
<el-table-column label="操作" align="center" width="160px">
<template #default="scope">
<el-button
@ -104,6 +100,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { handleTree } from '@/utils/tree'
import { CustomerSourceApi, CustomerSourceVO } from '@/api/crm/config/customersource'
import CustomerSourceForm from './CustomerSourceForm.vue'
@ -117,8 +114,8 @@ const { t } = useI18n() // 国际化
const loading = ref(true) //
const list = ref<CustomerSourceVO[]>([]) //
const queryParams = reactive({
customerSource: undefined,
isOpen: undefined
name: undefined,
status: undefined
})
const queryFormRef = ref() //
@ -161,17 +158,7 @@ const handleDelete = async (id: number) => {
//
await getList()
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await CustomerSourceApi.updateOpenStatus(id)
} catch {}
}
}
/** 展开/折叠操作 */
const isExpandAll = ref(true) //

View File

@ -7,12 +7,28 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户类型" prop="customerType">
<el-input v-model="formData.customerType" placeholder="请输入客户类型" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
<el-form-item label="客户类型" prop="name">
<el-input v-model="formData.name" placeholder="请输入客户类型" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
@ -21,6 +37,8 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { CustomerTypeApi, CustomerTypeVO } from '@/api/crm/config/customertype'
/** 客户类型 表单 */
defineOptions({ name: 'CustomerTypeForm' })
@ -34,13 +52,13 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
customerType: undefined,
isOpen: undefined as number | undefined,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined,
parentId: undefined as number | undefined,
})
const formRules = reactive({
customerType: [{ required: true, message: '客户类型不能为空', trigger: 'change' }],
name: [{ required: true, message: '客户类型不能为空', trigger: 'change' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
@ -59,7 +77,7 @@ const open = async (type: string, id?: number) => {
formData.value = await CustomerTypeApi.getCustomerType(id)
}
} finally {
formLoading.value = false
formLoading.value = false
}
}
}
@ -93,10 +111,10 @@ const submitForm = async () => {
const resetForm = (id:number) => {
formData.value = {
id: 0,
customerType: undefined,
name: undefined,
sort: undefined,
parentId:id?id:0,
isOpen:1
status: CommonStatusEnum.ENABLE,
}
formRef.value?.resetFields()
}

View File

@ -8,30 +8,29 @@
:inline="true"
label-width="68px"
>
<el-form-item label="客户类型" prop="customerType">
<el-form-item label="客户类型" prop="name">
<el-input
v-model="queryParams.customerType"
v-model="queryParams.name"
placeholder="请输入客户类型"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:customer-type:create']"
@ -57,20 +56,17 @@
v-if="refreshTable"
>
<el-table-column label="序号" align="center" type="index" width="60px" />
<el-table-column label="客户类型" align="left" prop="customerType" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px"/>
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="客户类型" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="120px">
</el-table-column>
<el-table-column label="操作" align="center" width="160px">
<template #default="scope">
<el-button
link
<el-button
link
type="primary"
@click="openForm('create', scope.row.id)"
v-hasPermi="['crm:customer-type:update']"
@ -104,6 +100,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { handleTree } from '@/utils/tree'
import { CustomerTypeApi, CustomerTypeVO } from '@/api/crm/config/customertype'
import CustomerTypeForm from './CustomerTypeForm.vue'
@ -117,8 +114,8 @@ const { t } = useI18n() // 国际化
const loading = ref(true) //
const list = ref<CustomerTypeVO[]>([]) //
const queryParams = reactive({
customerType: undefined,
isOpen: undefined,
name: undefined,
status: undefined,
})
const queryFormRef = ref() //
@ -163,12 +160,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await CustomerTypeApi.updateOpenStatus(id)
} catch {}
}
/** 展开/折叠操作 */

View File

@ -7,12 +7,28 @@
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="跟进状态" prop="followStatus">
<el-input v-model="formData.followStatus" placeholder="请输入" />
<el-form-item label="跟进状态" prop="name">
<el-input v-model="formData.name" placeholder="请输入" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
@ -22,6 +38,8 @@
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { FollowStatusApi, FollowStatusVO } from '@/api/crm/config/followstatus'
/** 跟进状态 表单 */
@ -36,12 +54,12 @@ const formLoading = ref(false) // 表单的加载中1修改时的数据加
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
followStatus: undefined,
isOpen: undefined as number | undefined,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined
})
const formRules = reactive({
followStatus: [{ required: true, message: '跟进状态不能为空', trigger: 'blur' }],
name: [{ required: true, message: '跟进状态不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
@ -92,8 +110,8 @@ const submitForm = async () => {
const resetForm = () => {
formData.value = {
id: 0,
followStatus: undefined,
isOpen: 1,
name: undefined,
status: CommonStatusEnum.ENABLE,
sort: undefined
}
formRef.value?.resetFields()

View File

@ -8,27 +8,24 @@
:inline="true"
label-width="68px"
>
<el-form-item label="跟进状态" prop="followStatus">
<el-form-item label="跟进状态" prop="name">
<el-input
v-model="queryParams.followStatus"
v-model="queryParams.name"
placeholder="请输入重要程度"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="isOpen">
<el-select
v-model="queryParams.isOpen"
placeholder="请选择"
clearable
class="!w-240px"
>
<el-option key="0" value="0" label="关闭" />
<el-option key="1" value="1" label="开启"/>
</el-select>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
@ -47,15 +44,12 @@
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="left" prop="sort" type="index" width="60px"/>
<el-table-column label="跟进状态" align="left" prop="followStatus" width="200px"/>
<el-table-column label="排序" align="left" prop="sort" width="100px" />
<el-table-column label="开启状态" align="left" prop="isOpen" min-widt="100px" >
<template #default="scope">
<el-switch v-model="scope.row.isOpen"
:active-value="1" :inactive-value="0" inline-prompt active-text="开启" inactive-text="关闭"
@click="changeOpenStatus(scope.row.id)"
/>
<el-table-column label="序号" align="center" prop="sort" type="index" width="60px"/>
<el-table-column label="跟进状态" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="开启状态" align="center" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160px">
@ -93,6 +87,7 @@
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { FollowStatusApi, FollowStatusVO } from '@/api/crm/config/followstatus'
import FollowStatusForm from './FollowStatusForm.vue'
@ -107,9 +102,9 @@ const list = ref<FollowStatusVO[]>([]) // 列表的数据
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
followStatus: undefined,
isOpen: undefined,
pageSize: 15,
name: undefined,
status: undefined,
sort: undefined
})
const queryFormRef = ref() //
@ -157,12 +152,6 @@ const handleDelete = async (id: number) => {
} catch {}
}
/**修改开启状态 */
const changeOpenStatus = async (id:number) => {
try {
await FollowStatusApi.updateOpenStatus(id)
} catch {}
}
/** 初始化 **/
onMounted(() => {

View File

@ -0,0 +1,153 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="适用部门">
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
<template #header>
全选/全不选:
<el-switch
v-model="treeNodeAll"
active-text="是"
inactive-text="否"
inline-prompt
@change="handleCheckedTreeNodeAll"
/>
全部展开/折叠:
<el-switch
v-model="menuExpand"
active-text="展开"
inactive-text="折叠"
inline-prompt
@change="handleCheckedTreeExpand"
/>
</template>
<el-tree
ref="treeRef"
:data="menuOptions"
:props="defaultProps"
empty-text="加载中,请稍候"
node-key="id"
show-checkbox
/>
</el-card>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { defaultProps, handleTree } from '@/utils/tree'
import { OpenSeaApi, OpenSeaVO } from '@/api/crm/config/opensea'
/** 公海管理 表单 */
defineOptions({ name: 'OpenSeaForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
openSea: undefined,
type: undefined as number | undefined,
depIds: undefined,
remark: undefined,
sort: undefined as number | undefined,
isOpen: undefined as number | undefined,
})
const formRules = reactive({
openSea: [{ required: true, message: '公海名称不能为空', trigger: 'blur' }],
type: [{ required: true, message: '公海类型1:内置2:自定义)不能为空', trigger: 'change' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
const treeRef = ref() // Ref
const menuOptions = ref<any[]>([]) //
const menuExpand = ref(false) // /
const treeNodeAll = ref(false) // /
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await OpenSeaApi.getOpenSea(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as OpenSeaVO
if (formType.value === 'create') {
await OpenSeaApi.createOpenSea(data)
message.success(t('common.createSuccess'))
} else {
await OpenSeaApi.updateOpenSea(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
openSea: undefined,
type: 2,
depIds: undefined,
remark: undefined,
sort: undefined,
isOpen: 1
}
formRef.value?.resetFields()
}
/** 全选/全不选 */
const handleCheckedTreeNodeAll = () => {
treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
}
/** 展开/折叠全部 */
const handleCheckedTreeExpand = () => {
const nodes = treeRef.value?.store.nodesMap
for (let node in nodes) {
if (nodes[node].expanded === menuExpand.value) {
continue
}
nodes[node].expanded = menuExpand.value
}
}
</script>

View File

@ -0,0 +1,131 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="公海名称" prop="openSea">
<el-input v-model="formData.openSea" placeholder="请输入公海名称" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
:min="0"
controls-position="right"
placeholder="请输入排序"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum,CrmOpenSeaTypeEnum } from '@/utils/constants'
import { OpenSeaApi, OpenSeaVO } from '@/api/crm/config/opensea'
/** 公海管理 表单 */
defineOptions({ name: 'OpenSeaForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
openSea: undefined,
type: CrmOpenSeaTypeEnum.CUSTOM,
depIds: undefined,
remark: undefined,
sort: undefined as number | undefined,
status: CommonStatusEnum.ENABLE,
})
const formRules = reactive({
openSea: [{ required: true, message: '公海名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await OpenSeaApi.getOpenSea(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as OpenSeaVO
if (formType.value === 'create') {
await OpenSeaApi.createOpenSea(data)
message.success(t('common.createSuccess'))
} else {
await OpenSeaApi.updateOpenSea(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
openSea: undefined,
type: CrmOpenSeaTypeEnum.CUSTOM,
depIds: undefined,
remark: undefined,
sort: undefined,
status: CommonStatusEnum.ENABLE
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,176 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="公海名称" prop="openSea">
<el-input
v-model="queryParams.openSea"
placeholder="请输入公海名称"
clearable
class="!w-240px"
/>
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:open-sea:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" prop="sort" type="index" width="60px" fixed />
<el-table-column label="公海名称" align="center" width="140px" prop="openSea" fixed/>
<el-table-column label="公海类型" align="center" width="100px" prop="type" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_OPEN_SEA_TYPE" :value="scope.row.type" />
</template>
</el-table-column>
<el-table-column label="排序" align="center" width="80px" prop="sort" />
<el-table-column label="适用部门" align="center" width="200px" prop="depIds" />
<el-table-column label="开启状态" align="center" width="80px" prop="status" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" min-width="120px" prop="remark" />
<el-table-column label="操作" align="center" width="200px" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:open-sea:update']"
>
适用部门
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:open-sea:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:open-sea:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<OpenSeaForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { OpenSeaApi, OpenSeaVO } from '@/api/crm/config/opensea'
import OpenSeaForm from './OpenSeaForm.vue'
/** 公海管理 列表 */
defineOptions({ name: 'OpenSea' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<OpenSeaVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 15,
openSea: undefined,
type: undefined,
status: undefined,
createTime: []
})
const queryFormRef = ref() //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await OpenSeaApi.getOpenSeaPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await OpenSeaApi.deleteOpenSea(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,241 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户姓名" prop="customerName">
<el-input v-model="formData.customerName" placeholder="请输入客户姓名" />
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input v-model="formData.expectAmount" placeholder="请输入期望金额" />
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
<el-form-item label="性别0:未知 1:男生2:女生)" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入居住地址" />
</el-form-item>
<el-form-item label="是否有车(0:没车1:有车)" prop="haveCar">
<el-input v-model="formData.haveCar" placeholder="请输入是否有车(0:没车1:有车)" />
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input v-model="formData.haveHouse" placeholder="请输入是否有房0:没房1:有房)" />
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input v-model="formData.haveProvidentFund" placeholder="请输入是否有公积金0:没公积金1有公积金" />
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input v-model="formData.haveSocialSecurity" placeholder="请输入是否有社保0:没社保1:有社保)" />
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input v-model="formData.haveGuaranteeSlip" placeholder="请输入是否有保单0:没保单1:有保单)" />
</el-form-item>
<el-form-item label="客户来源ID" prop="customerSourceId">
<el-input v-model="formData.customerSourceId" placeholder="请输入客户来源ID" />
</el-form-item>
<el-form-item label="客户类型ID" prop="customerTypeId">
<el-input v-model="formData.customerTypeId" placeholder="请输入客户类型ID" />
</el-form-item>
<el-form-item label="客户资料" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入客户资料" />
</el-form-item>
<el-form-item label="重要程度ID" prop="importLevelId">
<el-input v-model="formData.importLevelId" placeholder="请输入重要程度ID" />
</el-form-item>
<el-form-item label="跟进状态id" prop="followStatusId">
<el-input v-model="formData.followStatusId" placeholder="请输入跟进状态id" />
</el-form-item>
<el-form-item label="负责人ID" prop="ownerUserId">
<el-input v-model="formData.ownerUserId" placeholder="请输入负责人ID" />
</el-form-item>
<el-form-item label="成为负责人时间" prop="ownerTime">
<el-date-picker
v-model="formData.ownerTime"
type="date"
value-format="x"
placeholder="选择成为负责人时间"
/>
</el-form-item>
<el-form-item label="部门ID" prop="depId">
<el-input v-model="formData.depId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="最后跟进时间" prop="contactLastTime">
<el-date-picker
v-model="formData.contactLastTime"
type="date"
value-format="x"
placeholder="选择最后跟进时间"
/>
</el-form-item>
<el-form-item label="最后跟进内容" prop="contactLastContent">
<Editor v-model="formData.contactLastContent" height="150px" />
</el-form-item>
<el-form-item label="下次联系时间" prop="contactNextTime">
<el-date-picker
v-model="formData.contactNextTime"
type="date"
value-format="x"
placeholder="选择下次联系时间"
/>
</el-form-item>
<el-form-item label="锁定状态0:未锁1:锁定)" prop="lockStatus">
<el-radio-group v-model="formData.lockStatus">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="公海ID" prop="openSeaId">
<el-input v-model="formData.openSeaId" placeholder="请输入公海ID" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
/** 客户信息 表单 */
defineOptions({ name: 'CustomerInforForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
})
const formRules = reactive({
customerName: [{ required: true, message: '客户姓名不能为空', trigger: 'blur' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别0:未知 1:男生2:女生)不能为空', trigger: 'blur' }],
mobile: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
haveCar: [{ required: true, message: '是否有车(0:没车1:有车)不能为空', trigger: 'blur' }],
haveHouse: [{ required: true, message: '是否有房0:没房1:有房)不能为空', trigger: 'blur' }],
haveProvidentFund: [{ required: true, message: '是否有公积金0:没公积金1有公积金不能为空', trigger: 'blur' }],
haveSocialSecurity: [{ required: true, message: '是否有社保0:没社保1:有社保)不能为空', trigger: 'blur' }],
haveGuaranteeSlip: [{ required: true, message: '是否有保单0:没保单1:有保单)不能为空', trigger: 'blur' }],
customerSourceId: [{ required: true, message: '客户来源ID不能为空', trigger: 'blur' }],
customerTypeId: [{ required: true, message: '客户类型ID不能为空', trigger: 'blur' }],
importLevelId: [{ required: true, message: '重要程度ID不能为空', trigger: 'blur' }],
followStatusId: [{ required: true, message: '跟进状态id不能为空', trigger: 'blur' }],
depId: [{ required: true, message: '部门ID不能为空', trigger: 'blur' }],
lockStatus: [{ required: true, message: '锁定状态0:未锁1:锁定)不能为空', trigger: 'blur' }],
openSeaId: [{ required: true, message: '公海ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await CustomerInforApi.getCustomerInfor(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as CustomerInforVO
if (formType.value === 'create') {
await CustomerInforApi.createCustomerInfor(data)
message.success(t('common.createSuccess'))
} else {
await CustomerInforApi.updateCustomerInfor(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,465 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户姓名" prop="customerName" >
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户姓名"
clearable
class="!w-120px "
/>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户来源" prop="customerSourceId">
<el-cascader
v-model="queryParams.customerSourceId"
:show-all-levels="false"
:options="customerSourceOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户类型" prop="customerTypeId">
<el-cascader
v-model="queryParams.customerTypeId"
:show-all-levels="false"
:options="customerTypeOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="重要程度" prop="importLevelId">
<el-select
v-model="queryParams.importLevelId"
placeholder="请选择"
clearable
class="!w-120px margin-left:15px"
>
<el-option
v-for="iml in importLevelList"
:key="iml.id"
:value="iml.id"
:label="iml.name"
/>
</el-select>
</el-form-item>
<el-form-item label="跟进状态" prop="followStatusId">
<el-select
v-model="queryParams.followStatusId"
placeholder="请选择"
clearable
class="!w-120px "
>
<el-option
v-for="option in followstatusList"
:key="option.id"
:value="option.id"
:label="option.name"
/>
</el-select>
</el-form-item>
<el-form-item label="客户经理" prop="ownerUserId">
<el-select
v-model="queryParams.ownerUserId"
placeholder="请选择"
clearable
filterable
class="!w-120px"
>
<el-option
v-for="option in userList"
:key="option.id"
:value="option.id"
:label="option.nickname"
/>
</el-select>
</el-form-item>
<el-form-item label="所属部门" prop="depId">
<el-cascader
v-model="queryParams.depId"
:show-all-levels="false"
:options="depOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="是否有车" prop="haveCar">
<el-select v-model="queryParams.haveCar" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有房" prop="haveHouse">
<el-select v-model="queryParams.haveHouse" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="公积金" prop="haveProvidentFund">
<el-select v-model="queryParams.haveProvidentFund" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="社保" prop="haveSocialSecurity">
<el-select v-model="queryParams.haveSocialSecurity" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="最后跟进" prop="contactLastTime">
<el-date-picker
v-model="queryParams.contactLastTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="录入时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:customer-infor:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:customer-infor:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" width="60" type="index" fixed/>
<el-table-column label="客户姓名" align="center" prop="customerName" width="120px" fixed/>
<el-table-column label="手机号码" align="center" prop="mobile" width="140px" fixed/>
<el-table-column label="是否有车" align="center" prop="haveCar" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveCar" />
</template>
</el-table-column >
<el-table-column label="是否有房" align="center" prop="haveHouse" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveHouse" />
</template>
</el-table-column >
<el-table-column label="公积金" align="center" prop="haveProvidentFund" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveProvidentFund" />
</template>
</el-table-column >
<el-table-column label="社保" align="center" prop="haveSocialSecurity" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveSocialSecurity" />
</template>
</el-table-column >
<el-table-column label="客户来源" align="center" prop="customerSourceId" >
<template #default="scope">
<div>
{{ (customerSourceList.find((cs: any) => cs.id === scope.row.customerSourceId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户类型" align="center" prop="customerTypeId" >
<template #default="scope">
<div>
{{ (customerTypeList.find((cs: any) => cs.id === scope.row.customerTypeId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="重要程度" align="center" prop="importLevelId" >
<template #default="scope">
<div>
{{ importLevelList.find((cs) => cs.id === scope.row.importLevelId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="跟进状态" align="center" prop="followStatusId" >
<template #default="scope">
<div>
{{ followstatusList.find((cs) => cs.id === scope.row.followStatusId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户经理" align="center" prop="ownerUserId" >
<template #default="scope">
<div>
{{ userList.find((cs) => cs.id === scope.row.ownerUserId)?.nickname||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="所属部门" align="center" prop="depId" >
<template #default="scope">
<div>
{{ depList.find((cs) => cs.id === scope.row.depId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column
label="录入时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="最后跟进时间"
align="center"
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="最后跟进内容" align="center" prop="contactLastContent" width="180px"/>
<el-table-column label="客户资料" align="center" prop="remark" min-width="400px" />
<el-table-column label="操作" align="center" width="120px" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:customer-infor:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:customer-infor:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CustomerInforForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { buildTree } from '@/utils/tree'
import download from '@/utils/download'
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
import {ImportLevelApi,ImportLevelVO} from '@/api/crm/config/Importlevel'
import {FollowStatusApi,FollowStatusVO} from '@/api/crm/config/followstatus'
import {CustomerSourceApi,CustomerSourceVO} from '@/api/crm/config/customersource'
import {CustomerTypeApi,CustomerTypeVO} from '@/api/crm/config/customertype'
import * as UserApi from '@/api/system/user'
import * as DepApi from '@/api/system/dept'
import CustomerInforForm from './CustomerInforForm.vue'
/** 客户信息 列表 */
defineOptions({ name: 'AllCustomer' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<CustomerInforVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 15,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: [],
depId: undefined,
contactLastTime: [],
contactLastContent: undefined,
contactNextTime: [],
lockStatus: undefined,
openSeaId: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const importLevelList = ref<ImportLevelVO[]>([])
const followstatusList = ref<FollowStatusVO[]>([])
const userList = ref<UserApi.UserVO[]>([])
const depList = ref<DepApi.DeptVO[]>([])
const customerSourceList = ref<[]>([])
const customerTypeList = ref<[]>([])
let depOptions = ref<any>();
let customerSourceOptions = ref<any>();
let customerTypeOptions = ref<any>();
const cascaderProps= {
emitPath: false,
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerInforApi.getCustomerInforPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await CustomerInforApi.deleteCustomerInfor(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await CustomerInforApi.exportCustomerInfor(queryParams)
download.excel(data, '客户信息.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await getList()
//
importLevelList.value = await ImportLevelApi.getImportLevelList(null);
followstatusList.value = await FollowStatusApi.getFollowStatusList(null);
userList.value=await UserApi.getSimpleUsertList();
depList.value=await DepApi.getSimpleDeptList();
customerSourceList.value=await CustomerSourceApi.getCustomerSourceList(null);
customerTypeList.value=await CustomerTypeApi.getCustomerTypeList(null);
depOptions.value=buildTree(depList.value);
customerSourceOptions.value=buildTree(customerSourceList.value);
customerTypeOptions.value=buildTree(customerTypeList.value);
})
</script>

View File

@ -0,0 +1,241 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户姓名" prop="customerName">
<el-input v-model="formData.customerName" placeholder="请输入客户姓名" />
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input v-model="formData.expectAmount" placeholder="请输入期望金额" />
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
<el-form-item label="性别0:未知 1:男生2:女生)" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入居住地址" />
</el-form-item>
<el-form-item label="是否有车(0:没车1:有车)" prop="haveCar">
<el-input v-model="formData.haveCar" placeholder="请输入是否有车(0:没车1:有车)" />
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input v-model="formData.haveHouse" placeholder="请输入是否有房0:没房1:有房)" />
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input v-model="formData.haveProvidentFund" placeholder="请输入是否有公积金0:没公积金1有公积金" />
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input v-model="formData.haveSocialSecurity" placeholder="请输入是否有社保0:没社保1:有社保)" />
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input v-model="formData.haveGuaranteeSlip" placeholder="请输入是否有保单0:没保单1:有保单)" />
</el-form-item>
<el-form-item label="客户来源ID" prop="customerSourceId">
<el-input v-model="formData.customerSourceId" placeholder="请输入客户来源ID" />
</el-form-item>
<el-form-item label="客户类型ID" prop="customerTypeId">
<el-input v-model="formData.customerTypeId" placeholder="请输入客户类型ID" />
</el-form-item>
<el-form-item label="客户资料" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入客户资料" />
</el-form-item>
<el-form-item label="重要程度ID" prop="importLevelId">
<el-input v-model="formData.importLevelId" placeholder="请输入重要程度ID" />
</el-form-item>
<el-form-item label="跟进状态id" prop="followStatusId">
<el-input v-model="formData.followStatusId" placeholder="请输入跟进状态id" />
</el-form-item>
<el-form-item label="负责人ID" prop="ownerUserId">
<el-input v-model="formData.ownerUserId" placeholder="请输入负责人ID" />
</el-form-item>
<el-form-item label="成为负责人时间" prop="ownerTime">
<el-date-picker
v-model="formData.ownerTime"
type="date"
value-format="x"
placeholder="选择成为负责人时间"
/>
</el-form-item>
<el-form-item label="部门ID" prop="depId">
<el-input v-model="formData.depId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="最后跟进时间" prop="contactLastTime">
<el-date-picker
v-model="formData.contactLastTime"
type="date"
value-format="x"
placeholder="选择最后跟进时间"
/>
</el-form-item>
<el-form-item label="最后跟进内容" prop="contactLastContent">
<Editor v-model="formData.contactLastContent" height="150px" />
</el-form-item>
<el-form-item label="下次联系时间" prop="contactNextTime">
<el-date-picker
v-model="formData.contactNextTime"
type="date"
value-format="x"
placeholder="选择下次联系时间"
/>
</el-form-item>
<el-form-item label="锁定状态0:未锁1:锁定)" prop="lockStatus">
<el-radio-group v-model="formData.lockStatus">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="公海ID" prop="openSeaId">
<el-input v-model="formData.openSeaId" placeholder="请输入公海ID" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
/** 客户信息 表单 */
defineOptions({ name: 'CustomerInforForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
})
const formRules = reactive({
customerName: [{ required: true, message: '客户姓名不能为空', trigger: 'blur' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别0:未知 1:男生2:女生)不能为空', trigger: 'blur' }],
mobile: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
haveCar: [{ required: true, message: '是否有车(0:没车1:有车)不能为空', trigger: 'blur' }],
haveHouse: [{ required: true, message: '是否有房0:没房1:有房)不能为空', trigger: 'blur' }],
haveProvidentFund: [{ required: true, message: '是否有公积金0:没公积金1有公积金不能为空', trigger: 'blur' }],
haveSocialSecurity: [{ required: true, message: '是否有社保0:没社保1:有社保)不能为空', trigger: 'blur' }],
haveGuaranteeSlip: [{ required: true, message: '是否有保单0:没保单1:有保单)不能为空', trigger: 'blur' }],
customerSourceId: [{ required: true, message: '客户来源ID不能为空', trigger: 'blur' }],
customerTypeId: [{ required: true, message: '客户类型ID不能为空', trigger: 'blur' }],
importLevelId: [{ required: true, message: '重要程度ID不能为空', trigger: 'blur' }],
followStatusId: [{ required: true, message: '跟进状态id不能为空', trigger: 'blur' }],
depId: [{ required: true, message: '部门ID不能为空', trigger: 'blur' }],
lockStatus: [{ required: true, message: '锁定状态0:未锁1:锁定)不能为空', trigger: 'blur' }],
openSeaId: [{ required: true, message: '公海ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await CustomerInforApi.getCustomerInfor(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as CustomerInforVO
if (formType.value === 'create') {
await CustomerInforApi.createCustomerInfor(data)
message.success(t('common.createSuccess'))
} else {
await CustomerInforApi.updateCustomerInfor(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,454 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户姓名" prop="customerName" >
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户姓名"
clearable
class="!w-120px "
/>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户来源" prop="customerSourceId">
<el-cascader
v-model="queryParams.customerSourceId"
:show-all-levels="false"
:options="customerSourceOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户类型" prop="customerTypeId">
<el-cascader
v-model="queryParams.customerTypeId"
:show-all-levels="false"
:options="customerTypeOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="重要程度" prop="importLevelId">
<el-select
v-model="queryParams.importLevelId"
placeholder="请选择"
clearable
class="!w-120px margin-left:15px"
>
<el-option
v-for="iml in importLevelList"
:key="iml.id"
:value="iml.id"
:label="iml.name"
/>
</el-select>
</el-form-item>
<el-form-item label="跟进状态" prop="followStatusId">
<el-select
v-model="queryParams.followStatusId"
placeholder="请选择"
clearable
class="!w-120px "
>
<el-option
v-for="option in followstatusList"
:key="option.id"
:value="option.id"
:label="option.name"
/>
</el-select>
</el-form-item>
<el-form-item label="客户经理" prop="ownerUserId">
<el-select
v-model="queryParams.ownerUserId"
placeholder="请选择"
clearable
filterable
class="!w-120px"
>
<el-option
v-for="option in userList"
:key="option.id"
:value="option.id"
:label="option.nickname"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有车" prop="haveCar">
<el-select v-model="queryParams.haveCar" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有房" prop="haveHouse">
<el-select v-model="queryParams.haveHouse" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="公积金" prop="haveProvidentFund">
<el-select v-model="queryParams.haveProvidentFund" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="社保" prop="haveSocialSecurity">
<el-select v-model="queryParams.haveSocialSecurity" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="最后跟进" prop="contactLastTime">
<el-date-picker
v-model="queryParams.contactLastTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="录入时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:customer-infor:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:customer-infor:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" width="60" type="index" fixed/>
<el-table-column label="客户姓名" align="center" prop="customerName" width="120px" fixed/>
<el-table-column label="手机号码" align="center" prop="mobile" width="140px" fixed/>
<el-table-column label="是否有车" align="center" prop="haveCar" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveCar" />
</template>
</el-table-column >
<el-table-column label="是否有房" align="center" prop="haveHouse" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveHouse" />
</template>
</el-table-column >
<el-table-column label="公积金" align="center" prop="haveProvidentFund" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveProvidentFund" />
</template>
</el-table-column >
<el-table-column label="社保" align="center" prop="haveSocialSecurity" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveSocialSecurity" />
</template>
</el-table-column >
<el-table-column label="客户来源" align="center" prop="customerSourceId" >
<template #default="scope">
<div>
{{ (customerSourceList.find((cs: any) => cs.id === scope.row.customerSourceId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户类型" align="center" prop="customerTypeId" >
<template #default="scope">
<div>
{{ (customerTypeList.find((cs: any) => cs.id === scope.row.customerTypeId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="重要程度" align="center" prop="importLevelId" >
<template #default="scope">
<div>
{{ importLevelList.find((cs) => cs.id === scope.row.importLevelId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="跟进状态" align="center" prop="followStatusId" >
<template #default="scope">
<div>
{{ followstatusList.find((cs) => cs.id === scope.row.followStatusId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户经理" align="center" prop="ownerUserId" >
<template #default="scope">
<div>
{{ userList.find((cs) => cs.id === scope.row.ownerUserId)?.nickname||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="所属部门" align="center" prop="depId" >
<template #default="scope">
<div>
{{ depList.find((cs) => cs.id === scope.row.depId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column
label="录入时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="最后跟进时间"
align="center"
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="最后跟进内容" align="center" prop="contactLastContent" width="180px"/>
<el-table-column label="客户资料" align="center" prop="remark" min-width="400px" />
<el-table-column label="操作" align="center" width="120px" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:customer-infor:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:customer-infor:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CustomerInforForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { buildTree } from '@/utils/tree'
import download from '@/utils/download'
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
import {ImportLevelApi,ImportLevelVO} from '@/api/crm/config/Importlevel'
import {FollowStatusApi,FollowStatusVO} from '@/api/crm/config/followstatus'
import {CustomerSourceApi,CustomerSourceVO} from '@/api/crm/config/customersource'
import {CustomerTypeApi,CustomerTypeVO} from '@/api/crm/config/customertype'
import * as UserApi from '@/api/system/user'
import * as DepApi from '@/api/system/dept'
import CustomerInforForm from './CustomerInforForm.vue'
/** 客户信息 列表 */
defineOptions({ name: 'AllCustomer' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<CustomerInforVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 15,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: [],
depId: undefined,
contactLastTime: [],
contactLastContent: undefined,
contactNextTime: [],
lockStatus: undefined,
openSeaId: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const importLevelList = ref<ImportLevelVO[]>([])
const followstatusList = ref<FollowStatusVO[]>([])
const userList = ref<UserApi.UserVO[]>([])
const depList = ref<DepApi.DeptVO[]>([])
const customerSourceList = ref<[]>([])
const customerTypeList = ref<[]>([])
let depOptions = ref<any>();
let customerSourceOptions = ref<any>();
let customerTypeOptions = ref<any>();
const cascaderProps= {
emitPath: false,
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerInforApi.getCustomerInforPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await CustomerInforApi.deleteCustomerInfor(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await CustomerInforApi.exportCustomerInfor(queryParams)
download.excel(data, '客户信息.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await getList()
//
importLevelList.value = await ImportLevelApi.getImportLevelList(null);
followstatusList.value = await FollowStatusApi.getFollowStatusList(null);
userList.value=await UserApi.getSimpleUsertList();
depList.value=await DepApi.getSimpleDeptList();
customerSourceList.value=await CustomerSourceApi.getCustomerSourceList(null);
customerTypeList.value=await CustomerTypeApi.getCustomerTypeList(null);
depOptions.value=buildTree(depList.value);
customerSourceOptions.value=buildTree(customerSourceList.value);
customerTypeOptions.value=buildTree(customerTypeList.value);
})
</script>

View File

@ -0,0 +1,241 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户姓名" prop="customerName">
<el-input v-model="formData.customerName" placeholder="请输入客户姓名" />
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input v-model="formData.expectAmount" placeholder="请输入期望金额" />
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
<el-form-item label="性别0:未知 1:男生2:女生)" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入居住地址" />
</el-form-item>
<el-form-item label="是否有车(0:没车1:有车)" prop="haveCar">
<el-input v-model="formData.haveCar" placeholder="请输入是否有车(0:没车1:有车)" />
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input v-model="formData.haveHouse" placeholder="请输入是否有房0:没房1:有房)" />
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input v-model="formData.haveProvidentFund" placeholder="请输入是否有公积金0:没公积金1有公积金" />
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input v-model="formData.haveSocialSecurity" placeholder="请输入是否有社保0:没社保1:有社保)" />
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input v-model="formData.haveGuaranteeSlip" placeholder="请输入是否有保单0:没保单1:有保单)" />
</el-form-item>
<el-form-item label="客户来源ID" prop="customerSourceId">
<el-input v-model="formData.customerSourceId" placeholder="请输入客户来源ID" />
</el-form-item>
<el-form-item label="客户类型ID" prop="customerTypeId">
<el-input v-model="formData.customerTypeId" placeholder="请输入客户类型ID" />
</el-form-item>
<el-form-item label="客户资料" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入客户资料" />
</el-form-item>
<el-form-item label="重要程度ID" prop="importLevelId">
<el-input v-model="formData.importLevelId" placeholder="请输入重要程度ID" />
</el-form-item>
<el-form-item label="跟进状态id" prop="followStatusId">
<el-input v-model="formData.followStatusId" placeholder="请输入跟进状态id" />
</el-form-item>
<el-form-item label="负责人ID" prop="ownerUserId">
<el-input v-model="formData.ownerUserId" placeholder="请输入负责人ID" />
</el-form-item>
<el-form-item label="成为负责人时间" prop="ownerTime">
<el-date-picker
v-model="formData.ownerTime"
type="date"
value-format="x"
placeholder="选择成为负责人时间"
/>
</el-form-item>
<el-form-item label="部门ID" prop="depId">
<el-input v-model="formData.depId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="最后跟进时间" prop="contactLastTime">
<el-date-picker
v-model="formData.contactLastTime"
type="date"
value-format="x"
placeholder="选择最后跟进时间"
/>
</el-form-item>
<el-form-item label="最后跟进内容" prop="contactLastContent">
<Editor v-model="formData.contactLastContent" height="150px" />
</el-form-item>
<el-form-item label="下次联系时间" prop="contactNextTime">
<el-date-picker
v-model="formData.contactNextTime"
type="date"
value-format="x"
placeholder="选择下次联系时间"
/>
</el-form-item>
<el-form-item label="锁定状态0:未锁1:锁定)" prop="lockStatus">
<el-radio-group v-model="formData.lockStatus">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="公海ID" prop="openSeaId">
<el-input v-model="formData.openSeaId" placeholder="请输入公海ID" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
/** 客户信息 表单 */
defineOptions({ name: 'CustomerInforForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
})
const formRules = reactive({
customerName: [{ required: true, message: '客户姓名不能为空', trigger: 'blur' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别0:未知 1:男生2:女生)不能为空', trigger: 'blur' }],
mobile: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
haveCar: [{ required: true, message: '是否有车(0:没车1:有车)不能为空', trigger: 'blur' }],
haveHouse: [{ required: true, message: '是否有房0:没房1:有房)不能为空', trigger: 'blur' }],
haveProvidentFund: [{ required: true, message: '是否有公积金0:没公积金1有公积金不能为空', trigger: 'blur' }],
haveSocialSecurity: [{ required: true, message: '是否有社保0:没社保1:有社保)不能为空', trigger: 'blur' }],
haveGuaranteeSlip: [{ required: true, message: '是否有保单0:没保单1:有保单)不能为空', trigger: 'blur' }],
customerSourceId: [{ required: true, message: '客户来源ID不能为空', trigger: 'blur' }],
customerTypeId: [{ required: true, message: '客户类型ID不能为空', trigger: 'blur' }],
importLevelId: [{ required: true, message: '重要程度ID不能为空', trigger: 'blur' }],
followStatusId: [{ required: true, message: '跟进状态id不能为空', trigger: 'blur' }],
depId: [{ required: true, message: '部门ID不能为空', trigger: 'blur' }],
lockStatus: [{ required: true, message: '锁定状态0:未锁1:锁定)不能为空', trigger: 'blur' }],
openSeaId: [{ required: true, message: '公海ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await CustomerInforApi.getCustomerInfor(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as CustomerInforVO
if (formType.value === 'create') {
await CustomerInforApi.createCustomerInfor(data)
message.success(t('common.createSuccess'))
} else {
await CustomerInforApi.updateCustomerInfor(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,454 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户姓名" prop="customerName" >
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户姓名"
clearable
class="!w-120px "
/>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户来源" prop="customerSourceId">
<el-cascader
v-model="queryParams.customerSourceId"
:show-all-levels="false"
:options="customerSourceOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户类型" prop="customerTypeId">
<el-cascader
v-model="queryParams.customerTypeId"
:show-all-levels="false"
:options="customerTypeOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="重要程度" prop="importLevelId">
<el-select
v-model="queryParams.importLevelId"
placeholder="请选择"
clearable
class="!w-120px margin-left:15px"
>
<el-option
v-for="iml in importLevelList"
:key="iml.id"
:value="iml.id"
:label="iml.name"
/>
</el-select>
</el-form-item>
<el-form-item label="跟进状态" prop="followStatusId">
<el-select
v-model="queryParams.followStatusId"
placeholder="请选择"
clearable
class="!w-120px "
>
<el-option
v-for="option in followstatusList"
:key="option.id"
:value="option.id"
:label="option.name"
/>
</el-select>
</el-form-item>
<el-form-item label="客户经理" prop="ownerUserId">
<el-select
v-model="queryParams.ownerUserId"
placeholder="请选择"
clearable
filterable
class="!w-120px"
>
<el-option
v-for="option in userList"
:key="option.id"
:value="option.id"
:label="option.nickname"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有车" prop="haveCar">
<el-select v-model="queryParams.haveCar" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有房" prop="haveHouse">
<el-select v-model="queryParams.haveHouse" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="公积金" prop="haveProvidentFund">
<el-select v-model="queryParams.haveProvidentFund" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="社保" prop="haveSocialSecurity">
<el-select v-model="queryParams.haveSocialSecurity" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="最后跟进" prop="contactLastTime">
<el-date-picker
v-model="queryParams.contactLastTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="录入时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:customer-infor:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:customer-infor:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" width="60" type="index" fixed/>
<el-table-column label="客户姓名" align="center" prop="customerName" width="120px" fixed/>
<el-table-column label="手机号码" align="center" prop="mobile" width="140px" fixed/>
<el-table-column label="是否有车" align="center" prop="haveCar" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveCar" />
</template>
</el-table-column >
<el-table-column label="是否有房" align="center" prop="haveHouse" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveHouse" />
</template>
</el-table-column >
<el-table-column label="公积金" align="center" prop="haveProvidentFund" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveProvidentFund" />
</template>
</el-table-column >
<el-table-column label="社保" align="center" prop="haveSocialSecurity" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveSocialSecurity" />
</template>
</el-table-column >
<el-table-column label="客户来源" align="center" prop="customerSourceId" >
<template #default="scope">
<div>
{{ (customerSourceList.find((cs: any) => cs.id === scope.row.customerSourceId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户类型" align="center" prop="customerTypeId" >
<template #default="scope">
<div>
{{ (customerTypeList.find((cs: any) => cs.id === scope.row.customerTypeId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="重要程度" align="center" prop="importLevelId" >
<template #default="scope">
<div>
{{ importLevelList.find((cs) => cs.id === scope.row.importLevelId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="跟进状态" align="center" prop="followStatusId" >
<template #default="scope">
<div>
{{ followstatusList.find((cs) => cs.id === scope.row.followStatusId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户经理" align="center" prop="ownerUserId" >
<template #default="scope">
<div>
{{ userList.find((cs) => cs.id === scope.row.ownerUserId)?.nickname||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="所属部门" align="center" prop="depId" >
<template #default="scope">
<div>
{{ depList.find((cs) => cs.id === scope.row.depId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column
label="录入时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="最后跟进时间"
align="center"
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="最后跟进内容" align="center" prop="contactLastContent" width="180px"/>
<el-table-column label="客户资料" align="center" prop="remark" min-width="400px" />
<el-table-column label="操作" align="center" width="120px" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:customer-infor:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:customer-infor:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CustomerInforForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { buildTree } from '@/utils/tree'
import download from '@/utils/download'
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
import {ImportLevelApi,ImportLevelVO} from '@/api/crm/config/Importlevel'
import {FollowStatusApi,FollowStatusVO} from '@/api/crm/config/followstatus'
import {CustomerSourceApi,CustomerSourceVO} from '@/api/crm/config/customersource'
import {CustomerTypeApi,CustomerTypeVO} from '@/api/crm/config/customertype'
import * as UserApi from '@/api/system/user'
import * as DepApi from '@/api/system/dept'
import CustomerInforForm from './CustomerInforForm.vue'
/** 客户信息 列表 */
defineOptions({ name: 'AllCustomer' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<CustomerInforVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 15,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: [],
depId: undefined,
contactLastTime: [],
contactLastContent: undefined,
contactNextTime: [],
lockStatus: undefined,
openSeaId: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const importLevelList = ref<ImportLevelVO[]>([])
const followstatusList = ref<FollowStatusVO[]>([])
const userList = ref<UserApi.UserVO[]>([])
const depList = ref<DepApi.DeptVO[]>([])
const customerSourceList = ref<[]>([])
const customerTypeList = ref<[]>([])
let depOptions = ref<any>();
let customerSourceOptions = ref<any>();
let customerTypeOptions = ref<any>();
const cascaderProps= {
emitPath: false,
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerInforApi.getCustomerInforPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await CustomerInforApi.deleteCustomerInfor(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await CustomerInforApi.exportCustomerInfor(queryParams)
download.excel(data, '客户信息.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await getList()
//
importLevelList.value = await ImportLevelApi.getImportLevelList(null);
followstatusList.value = await FollowStatusApi.getFollowStatusList(null);
userList.value=await UserApi.getSimpleUsertList();
depList.value=await DepApi.getSimpleDeptList();
customerSourceList.value=await CustomerSourceApi.getCustomerSourceList(null);
customerTypeList.value=await CustomerTypeApi.getCustomerTypeList(null);
depOptions.value=buildTree(depList.value);
customerSourceOptions.value=buildTree(customerSourceList.value);
customerTypeOptions.value=buildTree(customerTypeList.value);
})
</script>

View File

@ -0,0 +1,241 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户姓名" prop="customerName">
<el-input v-model="formData.customerName" placeholder="请输入客户姓名" />
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input v-model="formData.expectAmount" placeholder="请输入期望金额" />
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
<el-form-item label="性别0:未知 1:男生2:女生)" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入居住地址" />
</el-form-item>
<el-form-item label="是否有车(0:没车1:有车)" prop="haveCar">
<el-input v-model="formData.haveCar" placeholder="请输入是否有车(0:没车1:有车)" />
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input v-model="formData.haveHouse" placeholder="请输入是否有房0:没房1:有房)" />
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input v-model="formData.haveProvidentFund" placeholder="请输入是否有公积金0:没公积金1有公积金" />
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input v-model="formData.haveSocialSecurity" placeholder="请输入是否有社保0:没社保1:有社保)" />
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input v-model="formData.haveGuaranteeSlip" placeholder="请输入是否有保单0:没保单1:有保单)" />
</el-form-item>
<el-form-item label="客户来源ID" prop="customerSourceId">
<el-input v-model="formData.customerSourceId" placeholder="请输入客户来源ID" />
</el-form-item>
<el-form-item label="客户类型ID" prop="customerTypeId">
<el-input v-model="formData.customerTypeId" placeholder="请输入客户类型ID" />
</el-form-item>
<el-form-item label="客户资料" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入客户资料" />
</el-form-item>
<el-form-item label="重要程度ID" prop="importLevelId">
<el-input v-model="formData.importLevelId" placeholder="请输入重要程度ID" />
</el-form-item>
<el-form-item label="跟进状态id" prop="followStatusId">
<el-input v-model="formData.followStatusId" placeholder="请输入跟进状态id" />
</el-form-item>
<el-form-item label="负责人ID" prop="ownerUserId">
<el-input v-model="formData.ownerUserId" placeholder="请输入负责人ID" />
</el-form-item>
<el-form-item label="成为负责人时间" prop="ownerTime">
<el-date-picker
v-model="formData.ownerTime"
type="date"
value-format="x"
placeholder="选择成为负责人时间"
/>
</el-form-item>
<el-form-item label="部门ID" prop="depId">
<el-input v-model="formData.depId" placeholder="请输入部门ID" />
</el-form-item>
<el-form-item label="最后跟进时间" prop="contactLastTime">
<el-date-picker
v-model="formData.contactLastTime"
type="date"
value-format="x"
placeholder="选择最后跟进时间"
/>
</el-form-item>
<el-form-item label="最后跟进内容" prop="contactLastContent">
<Editor v-model="formData.contactLastContent" height="150px" />
</el-form-item>
<el-form-item label="下次联系时间" prop="contactNextTime">
<el-date-picker
v-model="formData.contactNextTime"
type="date"
value-format="x"
placeholder="选择下次联系时间"
/>
</el-form-item>
<el-form-item label="锁定状态0:未锁1:锁定)" prop="lockStatus">
<el-radio-group v-model="formData.lockStatus">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="公海ID" prop="openSeaId">
<el-input v-model="formData.openSeaId" placeholder="请输入公海ID" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
/** 客户信息 表单 */
defineOptions({ name: 'CustomerInforForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
})
const formRules = reactive({
customerName: [{ required: true, message: '客户姓名不能为空', trigger: 'blur' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别0:未知 1:男生2:女生)不能为空', trigger: 'blur' }],
mobile: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
haveCar: [{ required: true, message: '是否有车(0:没车1:有车)不能为空', trigger: 'blur' }],
haveHouse: [{ required: true, message: '是否有房0:没房1:有房)不能为空', trigger: 'blur' }],
haveProvidentFund: [{ required: true, message: '是否有公积金0:没公积金1有公积金不能为空', trigger: 'blur' }],
haveSocialSecurity: [{ required: true, message: '是否有社保0:没社保1:有社保)不能为空', trigger: 'blur' }],
haveGuaranteeSlip: [{ required: true, message: '是否有保单0:没保单1:有保单)不能为空', trigger: 'blur' }],
customerSourceId: [{ required: true, message: '客户来源ID不能为空', trigger: 'blur' }],
customerTypeId: [{ required: true, message: '客户类型ID不能为空', trigger: 'blur' }],
importLevelId: [{ required: true, message: '重要程度ID不能为空', trigger: 'blur' }],
followStatusId: [{ required: true, message: '跟进状态id不能为空', trigger: 'blur' }],
depId: [{ required: true, message: '部门ID不能为空', trigger: 'blur' }],
lockStatus: [{ required: true, message: '锁定状态0:未锁1:锁定)不能为空', trigger: 'blur' }],
openSeaId: [{ required: true, message: '公海ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await CustomerInforApi.getCustomerInfor(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as CustomerInforVO
if (formType.value === 'create') {
await CustomerInforApi.createCustomerInfor(data)
message.success(t('common.createSuccess'))
} else {
await CustomerInforApi.updateCustomerInfor(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: undefined,
depId: undefined,
contactLastTime: undefined,
contactLastContent: undefined,
contactNextTime: undefined,
lockStatus: undefined,
openSeaId: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,454 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户姓名" prop="customerName" >
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户姓名"
clearable
class="!w-120px "
/>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户来源" prop="customerSourceId">
<el-cascader
v-model="queryParams.customerSourceId"
:show-all-levels="false"
:options="customerSourceOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="客户类型" prop="customerTypeId">
<el-cascader
v-model="queryParams.customerTypeId"
:show-all-levels="false"
:options="customerTypeOptions"
:props="cascaderProps"
clearable
class="!w-120px"
/>
</el-form-item>
<el-form-item label="重要程度" prop="importLevelId">
<el-select
v-model="queryParams.importLevelId"
placeholder="请选择"
clearable
class="!w-120px margin-left:15px"
>
<el-option
v-for="iml in importLevelList"
:key="iml.id"
:value="iml.id"
:label="iml.name"
/>
</el-select>
</el-form-item>
<el-form-item label="跟进状态" prop="followStatusId">
<el-select
v-model="queryParams.followStatusId"
placeholder="请选择"
clearable
class="!w-120px "
>
<el-option
v-for="option in followstatusList"
:key="option.id"
:value="option.id"
:label="option.name"
/>
</el-select>
</el-form-item>
<el-form-item label="客户经理" prop="ownerUserId">
<el-select
v-model="queryParams.ownerUserId"
placeholder="请选择"
clearable
filterable
class="!w-120px"
>
<el-option
v-for="option in userList"
:key="option.id"
:value="option.id"
:label="option.nickname"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有车" prop="haveCar">
<el-select v-model="queryParams.haveCar" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否有房" prop="haveHouse">
<el-select v-model="queryParams.haveHouse" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="公积金" prop="haveProvidentFund">
<el-select v-model="queryParams.haveProvidentFund" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="社保" prop="haveSocialSecurity">
<el-select v-model="queryParams.haveSocialSecurity" placeholder="请选择" clearable class="!w-120px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_HAVE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="最后跟进" prop="contactLastTime">
<el-date-picker
v-model="queryParams.contactLastTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="录入时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:customer-infor:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:customer-infor:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="center" width="60" type="index" fixed/>
<el-table-column label="客户姓名" align="center" prop="customerName" width="120px" fixed/>
<el-table-column label="手机号码" align="center" prop="mobile" width="140px" fixed/>
<el-table-column label="是否有车" align="center" prop="haveCar" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveCar" />
</template>
</el-table-column >
<el-table-column label="是否有房" align="center" prop="haveHouse" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveHouse" />
</template>
</el-table-column >
<el-table-column label="公积金" align="center" prop="haveProvidentFund" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveProvidentFund" />
</template>
</el-table-column >
<el-table-column label="社保" align="center" prop="haveSocialSecurity" >
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_HAVE_STATUS" :value="scope.row.haveSocialSecurity" />
</template>
</el-table-column >
<el-table-column label="客户来源" align="center" prop="customerSourceId" >
<template #default="scope">
<div>
{{ (customerSourceList.find((cs: any) => cs.id === scope.row.customerSourceId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户类型" align="center" prop="customerTypeId" >
<template #default="scope">
<div>
{{ (customerTypeList.find((cs: any) => cs.id === scope.row.customerTypeId) as any)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="重要程度" align="center" prop="importLevelId" >
<template #default="scope">
<div>
{{ importLevelList.find((cs) => cs.id === scope.row.importLevelId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="跟进状态" align="center" prop="followStatusId" >
<template #default="scope">
<div>
{{ followstatusList.find((cs) => cs.id === scope.row.followStatusId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="客户经理" align="center" prop="ownerUserId" >
<template #default="scope">
<div>
{{ userList.find((cs) => cs.id === scope.row.ownerUserId)?.nickname||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column label="所属部门" align="center" prop="depId" >
<template #default="scope">
<div>
{{ depList.find((cs) => cs.id === scope.row.depId)?.name||"未知" }}
</div>
</template>
</el-table-column >
<el-table-column
label="录入时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column
label="最后跟进时间"
align="center"
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="最后跟进内容" align="center" prop="contactLastContent" width="180px"/>
<el-table-column label="客户资料" align="center" prop="remark" min-width="400px" />
<el-table-column label="操作" align="center" width="120px" fixed="right">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:customer-infor:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:customer-infor:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CustomerInforForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { buildTree } from '@/utils/tree'
import download from '@/utils/download'
import { CustomerInforApi, CustomerInforVO } from '@/api/crm/customer/customerinfor'
import {ImportLevelApi,ImportLevelVO} from '@/api/crm/config/Importlevel'
import {FollowStatusApi,FollowStatusVO} from '@/api/crm/config/followstatus'
import {CustomerSourceApi,CustomerSourceVO} from '@/api/crm/config/customersource'
import {CustomerTypeApi,CustomerTypeVO} from '@/api/crm/config/customertype'
import * as UserApi from '@/api/system/user'
import * as DepApi from '@/api/system/dept'
import CustomerInforForm from './CustomerInforForm.vue'
/** 客户信息 列表 */
defineOptions({ name: 'AllCustomer' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<CustomerInforVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 15,
customerName: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
customerSourceId: undefined,
customerTypeId: undefined,
remark: undefined,
importLevelId: undefined,
followStatusId: undefined,
ownerUserId: undefined,
ownerTime: [],
depId: undefined,
contactLastTime: [],
contactLastContent: undefined,
contactNextTime: [],
lockStatus: undefined,
openSeaId: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const importLevelList = ref<ImportLevelVO[]>([])
const followstatusList = ref<FollowStatusVO[]>([])
const userList = ref<UserApi.UserVO[]>([])
const depList = ref<DepApi.DeptVO[]>([])
const customerSourceList = ref<[]>([])
const customerTypeList = ref<[]>([])
let depOptions = ref<any>();
let customerSourceOptions = ref<any>();
let customerTypeOptions = ref<any>();
const cascaderProps= {
emitPath: false,
}
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerInforApi.getCustomerInforPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await CustomerInforApi.deleteCustomerInfor(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await CustomerInforApi.exportCustomerInfor(queryParams)
download.excel(data, '客户信息.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await getList()
//
importLevelList.value = await ImportLevelApi.getImportLevelList(null);
followstatusList.value = await FollowStatusApi.getFollowStatusList(null);
userList.value=await UserApi.getSimpleUsertList();
depList.value=await DepApi.getSimpleDeptList();
customerSourceList.value=await CustomerSourceApi.getCustomerSourceList(null);
customerTypeList.value=await CustomerTypeApi.getCustomerTypeList(null);
depOptions.value=buildTree(depList.value);
customerSourceOptions.value=buildTree(customerSourceList.value);
customerTypeOptions.value=buildTree(customerTypeList.value);
})
</script>

View File

@ -0,0 +1,168 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="上传记录ID" prop="uploadId">
<el-input v-model="formData.uploadId" placeholder="请输入上传记录ID" />
</el-form-item>
<el-form-item label="客户姓名" prop="name">
<el-input v-model="formData.name" placeholder="请输入客户姓名" />
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input v-model="formData.expectAmount" placeholder="请输入期望金额" />
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model="formData.age" placeholder="请输入年龄" />
</el-form-item>
<el-form-item label="性别0:未知1:男生2:女生)" prop="sex">
<el-radio-group v-model="formData.sex">
<el-radio value="1">请选择字典生成</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入居住地址" />
</el-form-item>
<el-form-item label=" 是否有车(0:没车1:有车)" prop="haveCar">
<el-input v-model="formData.haveCar" placeholder="请输入 是否有车(0:没车1:有车)" />
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input v-model="formData.haveHouse" placeholder="请输入是否有房0:没房1:有房)" />
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input v-model="formData.haveProvidentFund" placeholder="请输入是否有公积金0:没公积金1有公积金" />
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input v-model="formData.haveSocialSecurity" placeholder="请输入是否有社保0:没社保1:有社保)" />
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input v-model="formData.haveGuaranteeSlip" placeholder="请输入是否有保单0:没保单1:有保单)" />
</el-form-item>
<el-form-item label="备注信息" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注信息" />
</el-form-item>
<el-form-item label="是否重复0:否1:是)" prop="isRepeat">
<el-input v-model="formData.isRepeat" placeholder="请输入是否重复0:否1:是)" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { UploadDetailApi, UploadDetailVO } from '@/api/crm/customer/uploaddetail'
/** 导入详情 表单 */
defineOptions({ name: 'UploadDetailForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
uploadId: undefined,
name: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
remark: undefined,
isRepeat: undefined
})
const formRules = reactive({
uploadId: [{ required: true, message: '上传记录ID不能为空', trigger: 'blur' }],
age: [{ required: true, message: '年龄不能为空', trigger: 'blur' }],
sex: [{ required: true, message: '性别0:未知1:男生2:女生)不能为空', trigger: 'blur' }],
mobile: [{ required: true, message: '手机号码不能为空', trigger: 'blur' }],
haveCar: [{ required: true, message: ' 是否有车(0:没车1:有车)不能为空', trigger: 'blur' }],
haveHouse: [{ required: true, message: '是否有房0:没房1:有房)不能为空', trigger: 'blur' }],
haveProvidentFund: [{ required: true, message: '是否有公积金0:没公积金1有公积金不能为空', trigger: 'blur' }],
haveSocialSecurity: [{ required: true, message: '是否有社保0:没社保1:有社保)不能为空', trigger: 'blur' }],
haveGuaranteeSlip: [{ required: true, message: '是否有保单0:没保单1:有保单)不能为空', trigger: 'blur' }],
isRepeat: [{ required: true, message: '是否重复0:否1:是)不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await UploadDetailApi.getUploadDetail(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as UploadDetailVO
if (formType.value === 'create') {
await UploadDetailApi.createUploadDetail(data)
message.success(t('common.createSuccess'))
} else {
await UploadDetailApi.updateUploadDetail(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
uploadId: undefined,
name: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
remark: undefined,
isRepeat: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,311 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="上传记录ID" prop="uploadId">
<el-input
v-model="queryParams.uploadId"
placeholder="请输入上传记录ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户姓名" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入客户姓名"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="期望金额" prop="expectAmount">
<el-input
v-model="queryParams.expectAmount"
placeholder="请输入期望金额"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input
v-model="queryParams.age"
placeholder="请输入年龄"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="性别0:未知1:男生2:女生)" prop="sex">
<el-select
v-model="queryParams.sex"
placeholder="请选择性别0:未知1:男生2:女生)"
clearable
class="!w-240px"
>
<el-option label="请选择字典生成" value="" />
</el-select>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input
v-model="queryParams.mobile"
placeholder="请输入手机号码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="居住地址" prop="address">
<el-input
v-model="queryParams.address"
placeholder="请输入居住地址"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label=" 是否有车(0:没车1:有车)" prop="haveCar">
<el-input
v-model="queryParams.haveCar"
placeholder="请输入 是否有车(0:没车1:有车)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否有房0:没房1:有房)" prop="haveHouse">
<el-input
v-model="queryParams.haveHouse"
placeholder="请输入是否有房0:没房1:有房)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否有公积金0:没公积金1有公积金" prop="haveProvidentFund">
<el-input
v-model="queryParams.haveProvidentFund"
placeholder="请输入是否有公积金0:没公积金1有公积金"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否有社保0:没社保1:有社保)" prop="haveSocialSecurity">
<el-input
v-model="queryParams.haveSocialSecurity"
placeholder="请输入是否有社保0:没社保1:有社保)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否有保单0:没保单1:有保单)" prop="haveGuaranteeSlip">
<el-input
v-model="queryParams.haveGuaranteeSlip"
placeholder="请输入是否有保单0:没保单1:有保单)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注信息" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注信息"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="是否重复0:否1:是)" prop="isRepeat">
<el-input
v-model="queryParams.isRepeat"
placeholder="请输入是否重复0:否1:是)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:upload-detail:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:upload-detail:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="客户ID" align="center" prop="id" />
<el-table-column label="上传记录ID" align="center" prop="uploadId" />
<el-table-column label="客户姓名" align="center" prop="name" />
<el-table-column label="期望金额" align="center" prop="expectAmount" />
<el-table-column label="年龄" align="center" prop="age" />
<el-table-column label="性别0:未知1:男生2:女生)" align="center" prop="sex" />
<el-table-column label="手机号码" align="center" prop="mobile" />
<el-table-column label="居住地址" align="center" prop="address" />
<el-table-column label=" 是否有车(0:没车1:有车)" align="center" prop="haveCar" />
<el-table-column label="是否有房0:没房1:有房)" align="center" prop="haveHouse" />
<el-table-column label="是否有公积金0:没公积金1有公积金" align="center" prop="haveProvidentFund" />
<el-table-column label="是否有社保0:没社保1:有社保)" align="center" prop="haveSocialSecurity" />
<el-table-column label="是否有保单0:没保单1:有保单)" align="center" prop="haveGuaranteeSlip" />
<el-table-column label="备注信息" align="center" prop="remark" />
<el-table-column label="是否重复0:否1:是)" align="center" prop="isRepeat" />
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:upload-detail:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:upload-detail:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<UploadDetailForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import download from '@/utils/download'
import { UploadDetailApi, UploadDetailVO } from '@/api/crm/customer/uploaddetail'
import UploadDetailForm from './UploadDetailForm.vue'
/** 导入详情 列表 */
defineOptions({ name: 'UploadDetail' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<UploadDetailVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
uploadId: undefined,
name: undefined,
expectAmount: undefined,
age: undefined,
sex: undefined,
mobile: undefined,
address: undefined,
haveCar: undefined,
haveHouse: undefined,
haveProvidentFund: undefined,
haveSocialSecurity: undefined,
haveGuaranteeSlip: undefined,
remark: undefined,
isRepeat: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await UploadDetailApi.getUploadDetailPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await UploadDetailApi.deleteUploadDetail(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await UploadDetailApi.exportUploadDetail(queryParams)
download.excel(data, '导入详情.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,98 @@
<template>
<Dialog v-model="dialogVisible" title="上传文件">
<el-upload
ref="uploadRef"
v-model:file-list="fileList"
:action="uploadUrl"
:auto-upload="false"
:data="data"
:disabled="formLoading"
:limit="1"
:on-change="handleFileChange"
:on-error="submitFormError"
:on-exceed="handleExceed"
:on-success="submitFormSuccess"
:http-request="httpRequest"
accept=".jpg, .png, .gif"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text"> 将文件拖到此处 <em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip" style="color: red">
提示仅允许导入 jpgpnggif 格式文件
</div>
</template>
</el-upload>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitFileForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { useUpload } from '@/components/UploadFile/src/useUpload'
defineOptions({ name: 'InfraFileForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const formLoading = ref(false) //
const fileList = ref([]) //
const data = ref({ path: '' })
const uploadRef = ref()
const { uploadUrl, httpRequest } = useUpload()
/** 打开弹窗 */
const open = async () => {
dialogVisible.value = true
resetForm()
}
defineExpose({ open }) // open
/** 处理上传的文件发生变化 */
const handleFileChange = (file) => {
data.value.path = file.name
}
/** 提交表单 */
const submitFileForm = () => {
if (fileList.value.length == 0) {
message.error('请上传文件')
return
}
unref(uploadRef)?.submit()
}
/** 文件上传成功处理 */
const emit = defineEmits(['success']) // success
const submitFormSuccess = () => {
//
dialogVisible.value = false
formLoading.value = false
unref(uploadRef)?.clearFiles()
//
message.success(t('common.createSuccess'))
emit('success')
}
/** 上传错误提示 */
const submitFormError = (): void => {
message.error('上传失败,请您重新上传!')
formLoading.value = false
}
/** 重置表单 */
const resetForm = () => {
//
formLoading.value = false
uploadRef.value?.clearFiles()
}
/** 文件数超出提示 */
const handleExceed = (): void => {
message.error('最多只能上传一个文件!')
}
</script>

View File

@ -0,0 +1,120 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="状态覆盖" prop="isCover">
<el-input v-model="formData.isCover" placeholder="请输入是否覆盖" />
</el-form-item>
<el-form-item label="所属公海" prop="openSeaId">
<el-input v-model="formData.openSeaId" placeholder="请输入公海ID" />
</el-form-item>
<el-form-item label="数据来源ID" prop="customerSourceId">
<el-input v-model="formData.customerSourceId" placeholder="请输入数据来源ID" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { UploadRecordApi, UploadRecordVO } from '@/api/crm/customer/uploadrecord'
/** 导入记录 表单 */
defineOptions({ name: 'UuploadRecordForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
fileName: undefined,
fileId: undefined,
totalCount: undefined,
repeatCount: undefined,
newCount: undefined,
isCover: undefined,
openSeaId: undefined,
customerSourceId: undefined,
creater: undefined
})
const formRules = reactive({
isCover: [{ required: true, message: '是否覆盖不能为空', trigger: 'blur' }],
openSeaId: [{ required: true, message: '公海不能为空', trigger: 'blur' }],
customerSourceId: [{ required: true, message: '数据来源不能为空', trigger: 'blur' }],
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await UploadRecordApi.getUuploadRecord(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as UploadRecordVO
if (formType.value === 'create') {
await UploadRecordApi.createUuploadRecord(data)
message.success(t('common.createSuccess'))
} else {
await UploadRecordApi.updateUuploadRecord(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
fileName: undefined,
fileId: undefined,
totalCount: undefined,
repeatCount: undefined,
newCount: undefined,
isCover: undefined,
openSeaId: undefined,
customerSourceId: undefined,
creater: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,203 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="文件名称" prop="fileName">
<el-input
v-model="queryParams.fileName"
placeholder="请输入上传文件名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="覆盖状态" prop="isCover">
<el-input
v-model="queryParams.isCover"
placeholder="请输入是否覆盖(0:不覆盖1覆盖)"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="所属公海" prop="openSeaId">
<el-input
v-model="queryParams.openSeaId"
placeholder="请输入公海ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="数据来源" prop="customerSourceId">
<el-input
v-model="queryParams.customerSourceId"
placeholder="请输入数据来源ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="导入时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:upload-record:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 导入
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" align="left" prop="sort" type="index" width="60px" fixed/>
<el-table-column label="文件名称" align="left" width="120px" prop="fileName" fixed/>
<el-table-column label="数据总数" align="left" width="120px" prop="totalCount" />
<el-table-column label="重复数量" align="left" width="120px" prop="repeatCount" />
<el-table-column label="新增数量" align="left" width="120px" prop="newCount" />
<el-table-column label="状态覆盖" align="left" width="120px" prop="isCover" />
<el-table-column label="所属公海" align="left" width="120px" prop="openSeaId" />
<el-table-column label="数据来源" align="left" width="120px" prop="customerSourceId" />
<el-table-column
label="创建时间"
align="left"
prop="createTime"
:formatter="dateFormatter"
min-width="180px"
/>
<el-table-column label="操作" align="center" width="120px" fixed="right">
<template #default="scope">
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:uupload-record:delete']"
>
详情
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<!-- <UploadRecordForm ref="formRef" @success="getList" /> -->
<FileForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import { UploadRecordApi, UploadRecordVO } from '@/api/crm/customer/uploadrecord'
import UploadRecordForm from './UploadRecordForm.vue'
import FileForm from './FileForm.vue'
import { onMounted } from 'vue'
/** 导入记录 列表 */
defineOptions({ name: 'UploadRecord' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<UploadRecordVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
fileName: undefined,
fileId: undefined,
totalCount: undefined,
repeatCount: undefined,
newCount: undefined,
isCover: undefined,
openSeaId: undefined,
customerSourceId: undefined,
creater: undefined,
createTime: []
})
const queryFormRef = ref() //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await UploadRecordApi.getUuploadRecordPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await UploadRecordApi.deleteUuploadRecord(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -0,0 +1,98 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="客户ID" prop="customerId">
<el-input v-model="formData.customerId" placeholder="请输入客户ID" />
</el-form-item>
<el-form-item label="跟进内容" prop="content">
<Editor v-model="formData.content" height="150px" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { FollwRecordApi, FollwRecordVO } from '@/api/crm/follw/follwrecord'
/** 跟进记录 表单 */
defineOptions({ name: 'FollwRecordForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
customerId: undefined,
content: undefined
})
const formRules = reactive({
customerId: [{ required: true, message: '客户ID不能为空', trigger: 'blur' }],
content: [{ required: true, message: '跟进内容不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await FollwRecordApi.getFollwRecord(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
const data = formData.value as unknown as FollwRecordVO
if (formType.value === 'create') {
await FollwRecordApi.createFollwRecord(data)
message.success(t('common.createSuccess'))
} else {
await FollwRecordApi.updateFollwRecord(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
customerId: undefined,
content: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,189 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="客户ID" prop="customerId">
<el-input
v-model="queryParams.customerId"
placeholder="请输入客户ID"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['crm:follw-record:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['crm:follw-record:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="唯一标识" align="center" prop="id" />
<el-table-column label="客户ID" align="center" prop="customerId" />
<el-table-column label="跟进内容" align="center" prop="content" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" min-width="120px">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['crm:follw-record:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['crm:follw-record:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<FollwRecordForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { FollwRecordApi, FollwRecordVO } from '@/api/crm/follw/follwrecord'
import FollwRecordForm from './FollwRecordForm.vue'
/** 跟进记录 列表 */
defineOptions({ name: 'FollwRecord' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<FollwRecordVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
customerId: undefined,
content: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await FollwRecordApi.getFollwRecordPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await FollwRecordApi.deleteFollwRecord(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await FollwRecordApi.exportFollwRecord(queryParams)
download.excel(data, '跟进记录.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>