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
04a42bc6
authored
Feb 19, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
📖
CRM:线索的跟进逻辑
parent
0ae6139e
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
152 additions
and
69 deletions
+152
-69
src/api/crm/backlog/index.ts
+0
-5
src/api/crm/clue/index.ts
+7
-2
src/views/crm/backlog/components/ClueFollowList.vue
+49
-21
src/views/crm/backlog/components/common.ts
+38
-0
src/views/crm/backlog/index.vue
+56
-39
src/views/crm/clue/detail/index.vue
+2
-2
No files found.
src/api/crm/backlog/index.ts
View file @
04a42bc6
...
...
@@ -6,11 +6,6 @@ export const getTodayCustomerCount = async () => {
return
await
request
.
get
({
url
:
'/crm/customer/today-customer-count'
})
}
// 2. 获得分配给我的线索数量
export
const
getFollowLeadsCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/clue/follow-leads-count'
})
}
// 3. 获得分配给我的客户数量
export
const
getFollowCustomerCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/customer/follow-customer-count'
})
...
...
src/api/crm/clue/index.ts
View file @
04a42bc6
...
...
@@ -68,6 +68,11 @@ export const transferClue = async (data: TransferReqVO) => {
}
// 线索转化为客户
export
const
transformClue
=
async
(
ids
:
number
[])
=>
{
return
await
request
.
put
({
url
:
'/crm/clue/transform?ids='
+
ids
.
join
(
','
)
})
export
const
transformClue
=
async
(
id
:
number
)
=>
{
return
await
request
.
put
({
url
:
'/crm/clue/transform'
,
params
:
{
id
}
})
}
// 获得分配给我的、待跟进的线索数量
export
const
getFollowClueCount
=
async
()
=>
{
return
await
request
.
get
({
url
:
'/crm/clue/follow-count'
})
}
src/views/crm/backlog/
tables/FollowLeads
.vue
→
src/views/crm/backlog/
components/ClueFollowList
.vue
View file @
04a42bc6
<!-- TODO: dhb52 待Clue页面更新后同步更新 -->
<!-- WHERE transformStatus = 0 AND followUpStatus = ? -->
<
template
>
<ContentWrap>
<div
class=
"pb-5 text-xl"
>
分配给我的线索
</div>
...
...
@@ -31,30 +29,40 @@
<!-- 列表 -->
<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=
"转化状态"
align=
"center"
prop=
"transformStatus"
>
<el-table-column
label=
"线索名称"
align=
"center"
prop=
"name"
fixed=
"left"
width=
"120"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.transformStatus"
/>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
name
}}
</el-link>
</
template
>
</el-table-column>
<el-table-column
label=
"
跟进状态"
align=
"center"
prop=
"followUpStatus
"
>
<el-table-column
label=
"
线索来源"
align=
"center"
prop=
"source"
width=
"100
"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.followUpStatus"
/>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_SOURCE"
:value=
"scope.row.source"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"手机号"
align=
"center"
prop=
"mobile"
width=
"120"
/>
<el-table-column
label=
"电话"
align=
"center"
prop=
"telephone"
width=
"130"
/>
<el-table-column
label=
"邮箱"
align=
"center"
prop=
"email"
width=
"180"
/>
<el-table-column
label=
"地址"
align=
"center"
prop=
"detailAddress"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"客户行业"
prop=
"industryId"
width=
"100"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_INDUSTRY"
:value=
"scope.row.industryId"
/>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"客户级别"
prop=
"level"
width=
"135"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_LEVEL"
:value=
"scope.row.level"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"线索名称"
align=
"center"
prop=
"name"
/>
<el-table-column
label=
"客户id"
align=
"center"
prop=
"customerId"
/>
<el-table-column
label=
"下次联系时间
"
:formatter=
"dateFormatter
"
align=
"center"
label=
"下次联系时间"
prop=
"contactNextTime"
:formatter=
"dateFormatter"
width=
"180px"
/>
<el-table-column
label=
"电话"
align=
"center"
prop=
"telephone"
/>
<el-table-column
label=
"手机号"
align=
"center"
prop=
"mobile"
/>
<el-table-column
label=
"地址"
align=
"center"
prop=
"address"
/>
<el-table-column
label=
"负责人"
align=
"center"
prop=
"ownerUserId"
/>
<el-table-column
align=
"center"
label=
"备注"
prop=
"remark"
width=
"200"
/>
<el-table-column
label=
"最后跟进时间"
align=
"center"
...
...
@@ -62,7 +70,16 @@
:formatter=
"dateFormatter"
width=
"180px"
/>
<el-table-column
label=
"备注"
align=
"center"
prop=
"remark"
/>
<el-table-column
align=
"center"
label=
"最后跟进记录"
prop=
"contactLastContent"
width=
"200"
/>
<el-table-column
align=
"center"
label=
"负责人"
prop=
"ownerUserName"
width=
"100px"
/>
<el-table-column
align=
"center"
label=
"所属部门"
prop=
"ownerUserDeptName"
width=
"100"
/>
<el-table-column
label=
"更新时间"
align=
"center"
prop=
"updateTime"
:formatter=
"dateFormatter"
width=
"180px"
/>
<el-table-column
label=
"创建时间"
align=
"center"
...
...
@@ -70,6 +87,7 @@
:formatter=
"dateFormatter"
width=
"180px"
/>
<el-table-column
align=
"center"
label=
"创建人"
prop=
"creatorName"
width=
"100px"
/>
</el-table>
<!-- 分页 -->
<Pagination
...
...
@@ -80,13 +98,14 @@
/>
</ContentWrap>
</template>
<
script
setup
lang=
"ts"
name=
"FollowLeads"
>
<
script
setup
lang=
"ts"
>
import
*
as
ClueApi
from
'@/api/crm/clue'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
{
FOLLOWUP_STATUS
}
from
'./common'
defineOptions
({
name
:
'CrmClueFollowList'
})
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
...
...
@@ -94,7 +113,7 @@ const queryParams = reactive({
pageNo
:
1
,
pageSize
:
10
,
followUpStatus
:
false
,
transformStatus
:
false
// 固定为【未转移】
transformStatus
:
false
})
const
queryFormRef
=
ref
()
// 搜索的表单
...
...
@@ -116,10 +135,19 @@ const handleQuery = () => {
getList
()
}
/** 打开线索详情 */
const
{
push
}
=
useRouter
()
const
openDetail
=
(
id
:
number
)
=>
{
push
({
name
:
'CrmClueDetail'
,
params
:
{
id
}
})
}
/** 激活时 */
onActivated
(
async
()
=>
{
await
getList
()
})
/** 初始化 **/
onMounted
(()
=>
{
getList
()
})
</
script
>
<
style
scoped
></
style
>
src/views/crm/backlog/components/common.ts
0 → 100644
View file @
04a42bc6
/** 跟进状态 */
export
const
FOLLOWUP_STATUS
=
[
{
label
:
'待跟进'
,
value
:
false
},
{
label
:
'已跟进'
,
value
:
true
}
]
/** 归属范围 */
export
const
SCENE_TYPES
=
[
{
label
:
'我负责的'
,
value
:
1
},
{
label
:
'我参与的'
,
value
:
2
},
{
label
:
'下属负责的'
,
value
:
3
}
]
/** 联系状态 */
export
const
CONTACT_STATUS
=
[
{
label
:
'今日需联系'
,
value
:
1
},
{
label
:
'已逾期'
,
value
:
2
},
{
label
:
'已联系'
,
value
:
3
}
]
/** 审批状态 */
export
const
AUDIT_STATUS
=
[
{
label
:
'已审批'
,
value
:
20
},
{
label
:
'待审批'
,
value
:
10
}
]
/** 回款提醒类型 */
export
const
RECEIVABLE_REMIND_TYPE
=
[
{
label
:
'待回款'
,
value
:
1
},
{
label
:
'已逾期'
,
value
:
2
},
{
label
:
'已回款'
,
value
:
3
}
]
/** 合同过期状态 */
export
const
CONTRACT_EXPIRY_TYPE
=
[
{
label
:
'即将过期'
,
value
:
1
},
{
label
:
'已过期'
,
value
:
2
}
]
src/views/crm/backlog/index.vue
View file @
04a42bc6
...
...
@@ -5,24 +5,24 @@
<div
v-for=
"(item, index) in leftSides"
:key=
"index"
:class=
"left
Type == item.infoType
? 'side-item-select' : 'side-item-default'"
:class=
"left
Menu == item.menu
? 'side-item-select' : 'side-item-default'"
class=
"side-item"
@
click=
"sideClick(item)"
>
{{
item
.
name
}}
<el-badge
v-if=
"item.
msgCount > 0"
:max=
"99"
:value=
"item.msgC
ount"
/>
<el-badge
v-if=
"item.
count > 0"
:max=
"99"
:value=
"item.c
ount"
/>
</div>
</div>
</el-col>
<el-col
:span=
"20"
:xs=
"24"
>
<TodayCustomer
v-if=
"left
Type
=== 'todayCustomer'"
/>
<
FollowLeads
v-if=
"leftType === 'followLeads
'"
/>
<CheckContract
v-if=
"left
Type
=== 'checkContract'"
/>
<CheckReceivables
v-if=
"left
Type
=== 'checkReceivables'"
/>
<EndContract
v-if=
"left
Type
=== 'endContract'"
/>
<FollowCustomer
v-if=
"left
Type
=== 'followCustomer'"
/>
<PutInPoolRemind
v-if=
"left
Type
=== 'putInPoolRemind'"
/>
<RemindReceivables
v-if=
"left
Type
=== 'remindReceivables'"
/>
<TodayCustomer
v-if=
"left
Menu
=== 'todayCustomer'"
/>
<
ClueFollowList
v-if=
"leftMenu === 'clueFollow
'"
/>
<CheckContract
v-if=
"left
Menu
=== 'checkContract'"
/>
<CheckReceivables
v-if=
"left
Menu
=== 'checkReceivables'"
/>
<EndContract
v-if=
"left
Menu
=== 'endContract'"
/>
<FollowCustomer
v-if=
"left
Menu
=== 'followCustomer'"
/>
<PutInPoolRemind
v-if=
"left
Menu
=== 'putInPoolRemind'"
/>
<RemindReceivables
v-if=
"left
Menu
=== 'remindReceivables'"
/>
</el-col>
</el-row>
</
template
>
...
...
@@ -33,15 +33,18 @@ import CheckContract from './tables/CheckContract.vue'
import
CheckReceivables
from
'./tables/CheckReceivables.vue'
import
EndContract
from
'./tables/EndContract.vue'
import
FollowCustomer
from
'./tables/FollowCustomer.vue'
import
FollowLeads
from
'./tables/FollowLeads
.vue'
import
ClueFollowList
from
'./components/ClueFollowList
.vue'
import
PutInPoolRemind
from
'./tables/PutInPoolRemind.vue'
import
RemindReceivables
from
'./tables/RemindReceivables.vue'
import
TodayCustomer
from
'./tables/TodayCustomer.vue'
import
*
as
ClueApi
from
'@/api/crm/clue'
const
leftType
=
ref
(
'todayCustomer'
)
defineOptions
({
name
:
'CrmBacklog'
})
const
leftMenu
=
ref
(
'todayCustomer'
)
const
todayCustomerCountRef
=
ref
(
0
)
const
followLeadsCountRef
=
ref
(
0
)
const
clueFollowCount
=
ref
(
0
)
const
followCustomerCountRef
=
ref
(
0
)
const
putInPoolCustomerRemindCountRef
=
ref
(
0
)
const
checkContractCountRef
=
ref
(
0
)
...
...
@@ -52,61 +55,75 @@ const endContractCountRef = ref(0)
const
leftSides
=
ref
([
{
name
:
'今日需联系客户'
,
infoType
:
'todayCustomer'
,
msgC
ount
:
todayCustomerCountRef
menu
:
'todayCustomer'
,
c
ount
:
todayCustomerCountRef
},
{
name
:
'分配给我的线索'
,
infoType
:
'followLeads
'
,
msgCount
:
followLeadsCountRef
menu
:
'clueFollow
'
,
count
:
clueFollowCount
},
{
name
:
'分配给我的客户'
,
infoType
:
'followCustomer'
,
msgC
ount
:
followCustomerCountRef
menu
:
'followCustomer'
,
c
ount
:
followCustomerCountRef
},
{
name
:
'待进入公海的客户'
,
infoType
:
'putInPoolRemind'
,
msgC
ount
:
putInPoolCustomerRemindCountRef
menu
:
'putInPoolRemind'
,
c
ount
:
putInPoolCustomerRemindCountRef
},
{
name
:
'待审核合同'
,
infoType
:
'checkContract'
,
msgC
ount
:
checkContractCountRef
menu
:
'checkContract'
,
c
ount
:
checkContractCountRef
},
{
name
:
'待审核回款'
,
infoType
:
'checkReceivables'
,
msgC
ount
:
checkReceivablesCountRef
menu
:
'checkReceivables'
,
c
ount
:
checkReceivablesCountRef
},
{
name
:
'待回款提醒'
,
infoType
:
'remindReceivables'
,
msgC
ount
:
remindReceivablesCountRef
menu
:
'remindReceivables'
,
c
ount
:
remindReceivablesCountRef
},
{
name
:
'即将到期的合同'
,
infoType
:
'endContract'
,
msgC
ount
:
endContractCountRef
menu
:
'endContract'
,
c
ount
:
endContractCountRef
}
])
/** 侧边点击 */
const
sideClick
=
(
item
:
any
)
=>
{
leftType
.
value
=
item
.
infoType
leftMenu
.
value
=
item
.
menu
}
const
getCount
=
()
=>
{
BacklogApi
.
getTodayCustomerCount
().
then
((
count
)
=>
(
todayCustomerCountRef
.
value
=
count
))
ClueApi
.
getFollowClueCount
().
then
((
count
)
=>
(
clueFollowCount
.
value
=
count
))
BacklogApi
.
getClueFollowListCount
().
then
((
count
)
=>
(
clueFollowCount
.
value
=
count
))
BacklogApi
.
getFollowCustomerCount
().
then
((
count
)
=>
(
followCustomerCountRef
.
value
=
count
))
BacklogApi
.
getPutInPoolCustomerRemindCount
().
then
(
(
count
)
=>
(
putInPoolCustomerRemindCountRef
.
value
=
count
)
)
BacklogApi
.
getCheckContractCount
().
then
((
count
)
=>
(
checkContractCountRef
.
value
=
count
))
BacklogApi
.
getCheckReceivablesCount
().
then
((
count
)
=>
(
checkReceivablesCountRef
.
value
=
count
))
BacklogApi
.
getRemindReceivablePlanCount
().
then
(
(
count
)
=>
(
remindReceivablesCountRef
.
value
=
count
)
)
BacklogApi
.
getEndContractCount
().
then
((
count
)
=>
(
endContractCountRef
.
value
=
count
))
}
/** 加载时读取待办数量 */
/** 激活时 */
onActivated
(
async
()
=>
{
getCount
()
})
/** 初始化 */
onMounted
(
async
()
=>
{
BacklogApi
.
getTodayCustomerCount
().
then
(
count
=>
todayCustomerCountRef
.
value
=
count
)
BacklogApi
.
getFollowLeadsCount
().
then
(
count
=>
followLeadsCountRef
.
value
=
count
)
BacklogApi
.
getFollowCustomerCount
().
then
(
count
=>
followCustomerCountRef
.
value
=
count
)
BacklogApi
.
getPutInPoolCustomerRemindCount
().
then
(
count
=>
putInPoolCustomerRemindCountRef
.
value
=
count
)
BacklogApi
.
getCheckContractCount
().
then
(
count
=>
checkContractCountRef
.
value
=
count
)
BacklogApi
.
getCheckReceivablesCount
().
then
(
count
=>
checkReceivablesCountRef
.
value
=
count
)
BacklogApi
.
getRemindReceivablePlanCount
().
then
(
count
=>
remindReceivablesCountRef
.
value
=
count
)
BacklogApi
.
getEndContractCount
().
then
(
count
=>
endContractCountRef
.
value
=
count
)
getCount
()
})
</
script
>
...
...
src/views/crm/clue/detail/index.vue
View file @
04a42bc6
...
...
@@ -18,7 +18,7 @@
>
转化为客户
</el-button>
<el-button
type=
"success"
disabled
>
已转化客户
</el-button>
<el-button
v-else
type=
"success"
disabled
>
已转化客户
</el-button>
</ClueDetailsHeader>
<el-col>
<el-tabs>
...
...
@@ -97,7 +97,7 @@ const transfer = () => {
/** 转化为客户 */
const
handleTransform
=
async
()
=>
{
await
message
.
confirm
(
`确定将【
${
clue
.
value
.
name
}
】转化为客户吗?`
)
await
ClueApi
.
transformClue
(
[
clueId
.
value
]
)
await
ClueApi
.
transformClue
(
clueId
.
value
)
message
.
success
(
`转化客户【
${
clue
.
value
.
name
}
】成功`
)
await
getClue
()
}
...
...
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