Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
8512fe6b
authored
Feb 22, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
✨
CRM:完善商机和联系人之间的关联
parent
01684aa6
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
86 additions
and
37 deletions
+86
-37
src/api/crm/contact/index.ts
+5
-0
src/views/crm/business/BusinessForm.vue
+23
-4
src/views/crm/business/components/BusinessList.vue
+2
-1
src/views/crm/business/detail/index.vue
+9
-8
src/views/crm/business/index.vue
+15
-18
src/views/crm/contact/ContactForm.vue
+24
-4
src/views/crm/contact/components/ContactList.vue
+7
-2
src/views/crm/contact/detail/index.vue
+1
-0
No files found.
src/api/crm/contact/index.ts
View file @
8512fe6b
...
@@ -47,6 +47,11 @@ export const getContactPageByCustomer = async (params: any) => {
...
@@ -47,6 +47,11 @@ export const getContactPageByCustomer = async (params: any) => {
return
await
request
.
get
({
url
:
`/crm/contact/page-by-customer`
,
params
})
return
await
request
.
get
({
url
:
`/crm/contact/page-by-customer`
,
params
})
}
}
// 查询 CRM 联系人列表,基于指定商机
export
const
getContactPageByBusiness
=
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
`/crm/contact/page-by-business`
,
params
})
}
// 查询 CRM 联系人详情
// 查询 CRM 联系人详情
export
const
getContact
=
async
(
id
:
number
)
=>
{
export
const
getContact
=
async
(
id
:
number
)
=>
{
return
await
request
.
get
({
url
:
`/crm/contact/get?id=`
+
id
})
return
await
request
.
get
({
url
:
`/crm/contact/get?id=`
+
id
})
...
...
src/views/crm/business/BusinessForm.vue
View file @
8512fe6b
...
@@ -31,7 +31,12 @@
...
@@ -31,7 +31,12 @@
</el-col>
</el-col>
<el-col
:span=
"8"
>
<el-col
:span=
"8"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-select
v-model=
"formData.customerId"
placeholder=
"请选择客户"
class=
"w-1/1"
>
<el-select
:disabled=
"formData.customerDefault"
v-model=
"formData.customerId"
placeholder=
"请选择客户"
class=
"w-1/1"
>
<el-option
<el-option
v-for=
"item in customerList"
v-for=
"item in customerList"
:key=
"item.id"
:key=
"item.id"
...
@@ -158,7 +163,9 @@ const formData = ref({
...
@@ -158,7 +163,9 @@ const formData = ref({
totalProductPrice
:
undefined
,
totalProductPrice
:
undefined
,
totalPrice
:
undefined
,
totalPrice
:
undefined
,
remark
:
undefined
,
remark
:
undefined
,
products
:
[]
products
:
[],
contactId
:
undefined
,
customerDefault
:
false
})
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
name
:
[{
required
:
true
,
message
:
'商机名称不能为空'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'商机名称不能为空'
,
trigger
:
'blur'
}],
...
@@ -197,7 +204,7 @@ watch(
...
@@ -197,7 +204,7 @@ watch(
)
)
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
,
customerId
?:
number
,
contactId
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
dialogTitle
.
value
=
t
(
'action.'
+
type
)
formType
.
value
=
type
formType
.
value
=
type
...
@@ -210,7 +217,17 @@ const open = async (type: string, id?: number) => {
...
@@ -210,7 +217,17 @@ const open = async (type: string, id?: number) => {
}
finally
{
}
finally
{
formLoading
.
value
=
false
formLoading
.
value
=
false
}
}
}
else
{
if
(
customerId
)
{
formData
.
value
.
customerId
=
customerId
formData
.
value
.
customerDefault
=
true
// 默认客户的选择,不允许变
}
// 自动关联 contactId 联系人编号
if
(
contactId
)
{
formData
.
value
.
contactId
=
contactId
}
}
}
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
// 加载商机状态类型列表
// 加载商机状态类型列表
statusTypeList
.
value
=
await
BusinessStatusApi
.
getBusinessStatusTypeSimpleList
()
statusTypeList
.
value
=
await
BusinessStatusApi
.
getBusinessStatusTypeSimpleList
()
...
@@ -264,7 +281,9 @@ const resetForm = () => {
...
@@ -264,7 +281,9 @@ const resetForm = () => {
totalProductPrice
:
undefined
,
totalProductPrice
:
undefined
,
totalPrice
:
undefined
,
totalPrice
:
undefined
,
remark
:
undefined
,
remark
:
undefined
,
products
:
[]
products
:
[],
contactId
:
undefined
,
customerDefault
:
false
}
}
formRef
.
value
?.
resetFields
()
formRef
.
value
?.
resetFields
()
}
}
...
...
src/views/crm/business/components/BusinessList.vue
View file @
8512fe6b
...
@@ -76,6 +76,7 @@ const props = defineProps<{
...
@@ -76,6 +76,7 @@ const props = defineProps<{
bizType
:
number
// 业务类型
bizType
:
number
// 业务类型
bizId
:
number
// 业务编号
bizId
:
number
// 业务编号
customerId
?:
number
// 关联联系人与商机时,需要传入 customerId 进行筛选
customerId
?:
number
// 关联联系人与商机时,需要传入 customerId 进行筛选
contactId
?:
number
// 特殊:联系人编号;在【联系人】详情中,可以传递联系人编号,默认新建的商机关联到该联系人
}
>
()
}
>
()
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
...
@@ -125,7 +126,7 @@ const handleQuery = () => {
...
@@ -125,7 +126,7 @@ const handleQuery = () => {
/** 添加操作 */
/** 添加操作 */
const
formRef
=
ref
()
const
formRef
=
ref
()
const
openForm
=
()
=>
{
const
openForm
=
()
=>
{
formRef
.
value
.
open
(
'create'
)
formRef
.
value
.
open
(
'create'
,
null
,
props
.
customerId
,
props
.
contactId
)
}
}
/** 打开联系人详情 */
/** 打开联系人详情 */
...
...
src/views/crm/business/detail/index.vue
View file @
8512fe6b
...
@@ -15,6 +15,14 @@
...
@@ -15,6 +15,14 @@
<el-tab-pane
label=
"详细资料"
>
<el-tab-pane
label=
"详细资料"
>
<BusinessDetailsInfo
:business=
"business"
/>
<BusinessDetailsInfo
:business=
"business"
/>
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"联系人"
lazy
>
<ContactList
:biz-id=
"business.id!"
:biz-type=
"BizTypeEnum.CRM_BUSINESS"
:business-id=
"business.id"
:customer-id=
"business.customerId"
/>
</el-tab-pane>
<el-tab-pane
label=
"操作日志"
>
<el-tab-pane
label=
"操作日志"
>
<OperateLogV2
:log-list=
"logList"
/>
<OperateLogV2
:log-list=
"logList"
/>
</el-tab-pane>
</el-tab-pane>
...
@@ -27,13 +35,6 @@
...
@@ -27,13 +35,6 @@
@
quit-team=
"close"
@
quit-team=
"close"
/>
/>
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"商机"
lazy
>
<BusinessList
:biz-id=
"business.id!"
:biz-type=
"BizTypeEnum.CRM_CONTACT"
:customer-id=
"business.customerId"
/>
</el-tab-pane>
</el-tabs>
</el-tabs>
</el-col>
</el-col>
<!-- 表单弹窗:添加/修改 -->
<!-- 表单弹窗:添加/修改 -->
...
@@ -46,7 +47,6 @@ import * as ContactApi from '@/api/crm/contact'
...
@@ -46,7 +47,6 @@ import * as ContactApi from '@/api/crm/contact'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
BusinessDetailsHeader
from
'./BusinessDetailsHeader.vue'
import
BusinessDetailsHeader
from
'./BusinessDetailsHeader.vue'
import
BusinessDetailsInfo
from
'./BusinessDetailsInfo.vue'
import
BusinessDetailsInfo
from
'./BusinessDetailsInfo.vue'
import
BusinessList
from
'@/views/crm/business/components/BusinessList.vue'
// 商机列表
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
PermissionList
from
'@/views/crm/permission/components/PermissionList.vue'
// 团队成员列表(权限)
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
BizTypeEnum
}
from
'@/api/crm/permission'
import
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
import
{
OperateLogV2VO
}
from
'@/api/system/operatelog'
...
@@ -54,6 +54,7 @@ import { getOperateLogPage } from '@/api/crm/operateLog'
...
@@ -54,6 +54,7 @@ import { getOperateLogPage } from '@/api/crm/operateLog'
import
ContactForm
from
'@/views/crm/contact/ContactForm.vue'
import
ContactForm
from
'@/views/crm/contact/ContactForm.vue'
import
CrmTransferForm
from
'@/views/crm/permission/components/TransferForm.vue'
import
CrmTransferForm
from
'@/views/crm/permission/components/TransferForm.vue'
import
FollowUpList
from
'@/views/crm/followup/index.vue'
import
FollowUpList
from
'@/views/crm/followup/index.vue'
import
ContactList
from
'@/views/crm/contact/components/ContactList.vue'
defineOptions
({
name
:
'CrmBusinessDetail'
})
defineOptions
({
name
:
'CrmBusinessDetail'
})
...
...
src/views/crm/business/index.vue
View file @
8512fe6b
...
@@ -38,6 +38,11 @@
...
@@ -38,6 +38,11 @@
<!-- 列表 -->
<!-- 列表 -->
<ContentWrap>
<ContentWrap>
<el-tabs
v-model=
"activeName"
@
tab-click=
"handleTabClick"
>
<el-tab-pane
label=
"我负责的"
name=
"1"
/>
<el-tab-pane
label=
"我参与的"
name=
"2"
/>
<el-tab-pane
label=
"下属负责的"
name=
"3"
/>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table
v-loading=
"loading"
:data=
"list"
:stripe=
"true"
:show-overflow-tooltip=
"true"
>
<el-table-column
align=
"center"
label=
"商机名称"
fixed=
"left"
prop=
"name"
width=
"160"
>
<el-table-column
align=
"center"
label=
"商机名称"
fixed=
"left"
prop=
"name"
width=
"160"
>
<template
#
default=
"scope"
>
<template
#
default=
"scope"
>
...
@@ -157,6 +162,7 @@ import download from '@/utils/download'
...
@@ -157,6 +162,7 @@ import download from '@/utils/download'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
*
as
BusinessApi
from
'@/api/crm/business'
import
BusinessForm
from
'./BusinessForm.vue'
import
BusinessForm
from
'./BusinessForm.vue'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
erpPriceTableColumnFormatter
}
from
'@/utils'
import
{
TabsPaneContext
}
from
'element-plus'
defineOptions
({
name
:
'CrmBusiness'
})
defineOptions
({
name
:
'CrmBusiness'
})
...
@@ -169,27 +175,12 @@ const list = ref([]) // 列表的数据
...
@@ -169,27 +175,12 @@ const list = ref([]) // 列表的数据
const
queryParams
=
reactive
({
const
queryParams
=
reactive
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
name
:
null
,
sceneType
:
'1'
,
// 默认和 activeName 相等
statusTypeId
:
null
,
name
:
null
statusId
:
null
,
contactNextTime
:
[],
customerId
:
null
,
dealTime
:
[],
price
:
null
,
discountPercent
:
null
,
productPrice
:
null
,
remark
:
null
,
ownerUserId
:
null
,
createTime
:
[],
roUserIds
:
null
,
rwUserIds
:
null
,
endStatus
:
null
,
endRemark
:
null
,
contactLastTime
:
[],
followUpStatus
:
null
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
activeName
=
ref
(
'1'
)
// 列表 tab
/** 查询列表 */
/** 查询列表 */
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
...
@@ -215,6 +206,12 @@ const resetQuery = () => {
...
@@ -215,6 +206,12 @@ const resetQuery = () => {
handleQuery
()
handleQuery
()
}
}
/** tab 切换 */
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
queryParams
.
sceneType
=
tab
.
paneName
handleQuery
()
}
/** 打开客户详情 */
/** 打开客户详情 */
const
{
currentRoute
,
push
}
=
useRouter
()
const
{
currentRoute
,
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
const
openDetail
=
(
id
:
number
)
=>
{
...
...
src/views/crm/contact/ContactForm.vue
View file @
8512fe6b
...
@@ -33,7 +33,12 @@
...
@@ -33,7 +33,12 @@
<el-row>
<el-row>
<el-col
:span=
"12"
>
<el-col
:span=
"12"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-form-item
label=
"客户名称"
prop=
"customerId"
>
<el-select
v-model=
"formData.customerId"
placeholder=
"请选择客户"
class=
"w-1/1"
>
<el-select
:disabled=
"formData.customerDefault"
v-model=
"formData.customerId"
placeholder=
"请选择客户"
class=
"w-1/1"
>
<el-option
<el-option
v-for=
"item in customerList"
v-for=
"item in customerList"
:key=
"item.id"
:key=
"item.id"
...
@@ -198,7 +203,9 @@ const formData = ref({
...
@@ -198,7 +203,9 @@ const formData = ref({
master
:
false
,
master
:
false
,
post
:
undefined
,
post
:
undefined
,
parentId
:
undefined
,
parentId
:
undefined
,
remark
:
undefined
remark
:
undefined
,
businessId
:
undefined
,
customerDefault
:
false
})
})
const
formRules
=
reactive
({
const
formRules
=
reactive
({
name
:
[{
required
:
true
,
message
:
'姓名不能为空'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'姓名不能为空'
,
trigger
:
'blur'
}],
...
@@ -212,7 +219,7 @@ const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
...
@@ -212,7 +219,7 @@ const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
// 联系人列表
const
contactList
=
ref
<
ContactApi
.
ContactVO
[]
>
([])
// 联系人列表
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
,
customerId
?:
number
,
businessId
?:
number
)
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
dialogTitle
.
value
=
t
(
'action.'
+
type
)
dialogTitle
.
value
=
t
(
'action.'
+
type
)
formType
.
value
=
type
formType
.
value
=
type
...
@@ -225,8 +232,19 @@ const open = async (type: string, id?: number) => {
...
@@ -225,8 +232,19 @@ const open = async (type: string, id?: number) => {
}
finally
{
}
finally
{
formLoading
.
value
=
false
formLoading
.
value
=
false
}
}
}
else
{
if
(
customerId
)
{
formData
.
value
.
customerId
=
customerId
formData
.
value
.
customerDefault
=
true
// 默认客户的选择,不允许变
}
// 自动关联 businessId 商机编号
if
(
businessId
)
{
formData
.
value
.
businessId
=
businessId
}
}
}
// 获得联系人列表
contactList
.
value
=
await
ContactApi
.
getSimpleContactList
()
contactList
.
value
=
await
ContactApi
.
getSimpleContactList
()
// 获得客户列表
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
customerList
.
value
=
await
CustomerApi
.
getCustomerSimpleList
()
// 获得地区列表
// 获得地区列表
areaList
.
value
=
await
AreaApi
.
getAreaTree
()
areaList
.
value
=
await
AreaApi
.
getAreaTree
()
...
@@ -284,7 +302,9 @@ const resetForm = () => {
...
@@ -284,7 +302,9 @@ const resetForm = () => {
master
:
false
,
master
:
false
,
post
:
undefined
,
post
:
undefined
,
parentId
:
undefined
,
parentId
:
undefined
,
remark
:
undefined
remark
:
undefined
,
businessId
:
undefined
,
customerDefault
:
false
}
}
formRef
.
value
?.
resetFields
()
formRef
.
value
?.
resetFields
()
}
}
...
...
src/views/crm/contact/components/ContactList.vue
View file @
8512fe6b
...
@@ -25,7 +25,6 @@
...
@@ -25,7 +25,6 @@
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.master"
/>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.master"
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<!-- TODO 芋艿:【操作:设为首要联系人】 -->
</el-table>
</el-table>
<!-- 分页 -->
<!-- 分页 -->
<Pagination
<Pagination
...
@@ -49,6 +48,8 @@ defineOptions({ name: 'CrmContactList' })
...
@@ -49,6 +48,8 @@ defineOptions({ name: 'CrmContactList' })
const
props
=
defineProps
<
{
const
props
=
defineProps
<
{
bizType
:
number
// 业务类型
bizType
:
number
// 业务类型
bizId
:
number
// 业务编号
bizId
:
number
// 业务编号
customerId
:
number
// 特殊:客户编号;在【商机】详情中,可以传递客户编号,默认新建的联系人关联到该客户
businessId
:
number
// 特殊:商机编号;在【商机】详情中,可以传递商机编号,默认新建的联系人关联到该商机
}
>
()
}
>
()
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
...
@@ -73,6 +74,10 @@ const getList = async () => {
...
@@ -73,6 +74,10 @@ const getList = async () => {
queryParams
.
customerId
=
props
.
bizId
queryParams
.
customerId
=
props
.
bizId
data
=
await
ContactApi
.
getContactPageByCustomer
(
queryParams
)
data
=
await
ContactApi
.
getContactPageByCustomer
(
queryParams
)
break
break
case
BizTypeEnum
.
CRM_BUSINESS
:
queryParams
.
businessId
=
props
.
bizId
data
=
await
ContactApi
.
getContactPageByBusiness
(
queryParams
)
break
default
:
default
:
return
return
}
}
...
@@ -92,7 +97,7 @@ const handleQuery = () => {
...
@@ -92,7 +97,7 @@ const handleQuery = () => {
/** 添加操作 */
/** 添加操作 */
const
formRef
=
ref
()
const
formRef
=
ref
()
const
openForm
=
()
=>
{
const
openForm
=
()
=>
{
formRef
.
value
.
open
(
'create'
)
formRef
.
value
.
open
(
'create'
,
undefined
,
props
.
customerId
,
props
.
businessId
)
}
}
/** 打开联系人详情 */
/** 打开联系人详情 */
...
...
src/views/crm/contact/detail/index.vue
View file @
8512fe6b
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
:biz-id=
"contact.id!"
:biz-id=
"contact.id!"
:biz-type=
"BizTypeEnum.CRM_CONTACT"
:biz-type=
"BizTypeEnum.CRM_CONTACT"
:customer-id=
"contact.customerId"
:customer-id=
"contact.customerId"
:contact-id=
"contact.id"
/>
/>
</el-tab-pane>
</el-tab-pane>
</el-tabs>
</el-tabs>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment