Skip to content

Commit 04a42bc

Browse files
committed
📖 CRM:线索的跟进逻辑
1 parent 0ae6139 commit 04a42bc

File tree

6 files changed

+152
-69
lines changed

6 files changed

+152
-69
lines changed

src/api/crm/backlog/index.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ export const getTodayCustomerCount = async () => {
66
return await request.get({ url: '/crm/customer/today-customer-count' })
77
}
88

9-
// 2. 获得分配给我的线索数量
10-
export const getFollowLeadsCount = async () => {
11-
return await request.get({ url: '/crm/clue/follow-leads-count' })
12-
}
13-
149
// 3. 获得分配给我的客户数量
1510
export const getFollowCustomerCount = async () => {
1611
return await request.get({ url: '/crm/customer/follow-customer-count' })

src/api/crm/clue/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ export const transferClue = async (data: TransferReqVO) => {
6868
}
6969

7070
// 线索转化为客户
71-
export const transformClue = async (ids: number[]) => {
72-
return await request.put({ url: '/crm/clue/transform?ids=' + ids.join(',') })
71+
export const transformClue = async (id: number) => {
72+
return await request.put({ url: '/crm/clue/transform', params: { id } })
73+
}
74+
75+
// 获得分配给我的、待跟进的线索数量
76+
export const getFollowClueCount = async () => {
77+
return await request.get({ url: '/crm/clue/follow-count' })
7378
}

src/views/crm/backlog/tables/FollowLeads.vue renamed to src/views/crm/backlog/components/ClueFollowList.vue

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
<!-- TODO: dhb52 待Clue页面更新后同步更新 -->
2-
<!-- WHERE transformStatus = 0 AND followUpStatus = ? -->
31
<template>
42
<ContentWrap>
53
<div class="pb-5 text-xl">分配给我的线索</div>
@@ -31,45 +29,65 @@
3129
<!-- 列表 -->
3230
<ContentWrap>
3331
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
34-
<el-table-column label="编号" align="center" prop="id" />
35-
<el-table-column label="转化状态" align="center" prop="transformStatus">
32+
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="120">
3633
<template #default="scope">
37-
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.transformStatus" />
34+
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
35+
{{ scope.row.name }}
36+
</el-link>
3837
</template>
3938
</el-table-column>
40-
<el-table-column label="跟进状态" align="center" prop="followUpStatus">
39+
<el-table-column label="线索来源" align="center" prop="source" width="100">
4140
<template #default="scope">
42-
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.followUpStatus" />
41+
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_SOURCE" :value="scope.row.source" />
42+
</template>
43+
</el-table-column>
44+
<el-table-column label="手机号" align="center" prop="mobile" width="120" />
45+
<el-table-column label="电话" align="center" prop="telephone" width="130" />
46+
<el-table-column label="邮箱" align="center" prop="email" width="180" />
47+
<el-table-column label="地址" align="center" prop="detailAddress" width="180" />
48+
<el-table-column align="center" label="客户行业" prop="industryId" width="100">
49+
<template #default="scope">
50+
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_INDUSTRY" :value="scope.row.industryId" />
51+
</template>
52+
</el-table-column>
53+
<el-table-column align="center" label="客户级别" prop="level" width="135">
54+
<template #default="scope">
55+
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_LEVEL" :value="scope.row.level" />
4356
</template>
4457
</el-table-column>
45-
<el-table-column label="线索名称" align="center" prop="name" />
46-
<el-table-column label="客户id" align="center" prop="customerId" />
4758
<el-table-column
48-
label="下次联系时间"
59+
:formatter="dateFormatter"
4960
align="center"
61+
label="下次联系时间"
5062
prop="contactNextTime"
51-
:formatter="dateFormatter"
5263
width="180px"
5364
/>
54-
<el-table-column label="电话" align="center" prop="telephone" />
55-
<el-table-column label="手机号" align="center" prop="mobile" />
56-
<el-table-column label="地址" align="center" prop="address" />
57-
<el-table-column label="负责人" align="center" prop="ownerUserId" />
65+
<el-table-column align="center" label="备注" prop="remark" width="200" />
5866
<el-table-column
5967
label="最后跟进时间"
6068
align="center"
6169
prop="contactLastTime"
6270
:formatter="dateFormatter"
6371
width="180px"
6472
/>
65-
<el-table-column label="备注" align="center" prop="remark" />
73+
<el-table-column align="center" label="最后跟进记录" prop="contactLastContent" width="200" />
74+
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
75+
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100" />
76+
<el-table-column
77+
label="更新时间"
78+
align="center"
79+
prop="updateTime"
80+
:formatter="dateFormatter"
81+
width="180px"
82+
/>
6683
<el-table-column
6784
label="创建时间"
6885
align="center"
6986
prop="createTime"
7087
:formatter="dateFormatter"
7188
width="180px"
7289
/>
90+
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
7391
</el-table>
7492
<!-- 分页 -->
7593
<Pagination
@@ -80,21 +98,22 @@
8098
/>
8199
</ContentWrap>
82100
</template>
83-
84-
<script setup lang="ts" name="FollowLeads">
101+
<script setup lang="ts">
85102
import * as ClueApi from '@/api/crm/clue'
86103
import { DICT_TYPE } from '@/utils/dict'
87104
import { dateFormatter } from '@/utils/formatTime'
88105
import { FOLLOWUP_STATUS } from './common'
89106
107+
defineOptions({ name: 'CrmClueFollowList' })
108+
90109
const loading = ref(true) // 列表的加载中
91110
const total = ref(0) // 列表的总页数
92111
const list = ref([]) // 列表的数据
93112
const queryParams = reactive({
94113
pageNo: 1,
95114
pageSize: 10,
96115
followUpStatus: false,
97-
transformStatus: false // 固定为【未转移】
116+
transformStatus: false
98117
})
99118
const queryFormRef = ref() // 搜索的表单
100119
@@ -116,10 +135,19 @@ const handleQuery = () => {
116135
getList()
117136
}
118137
138+
/** 打开线索详情 */
139+
const { push } = useRouter()
140+
const openDetail = (id: number) => {
141+
push({ name: 'CrmClueDetail', params: { id } })
142+
}
143+
144+
/** 激活时 */
145+
onActivated(async () => {
146+
await getList()
147+
})
148+
119149
/** 初始化 **/
120150
onMounted(() => {
121151
getList()
122152
})
123153
</script>
124-
125-
<style scoped></style>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/** 跟进状态 */
2+
export const FOLLOWUP_STATUS = [
3+
{ label: '待跟进', value: false },
4+
{ label: '已跟进', value: true }
5+
]
6+
7+
/** 归属范围 */
8+
export const SCENE_TYPES = [
9+
{ label: '我负责的', value: 1 },
10+
{ label: '我参与的', value: 2 },
11+
{ label: '下属负责的', value: 3 }
12+
]
13+
14+
/** 联系状态 */
15+
export const CONTACT_STATUS = [
16+
{ label: '今日需联系', value: 1 },
17+
{ label: '已逾期', value: 2 },
18+
{ label: '已联系', value: 3 }
19+
]
20+
21+
/** 审批状态 */
22+
export const AUDIT_STATUS = [
23+
{ label: '已审批', value: 20 },
24+
{ label: '待审批', value: 10 }
25+
]
26+
27+
/** 回款提醒类型 */
28+
export const RECEIVABLE_REMIND_TYPE = [
29+
{ label: '待回款', value: 1 },
30+
{ label: '已逾期', value: 2 },
31+
{ label: '已回款', value: 3 }
32+
]
33+
34+
/** 合同过期状态 */
35+
export const CONTRACT_EXPIRY_TYPE = [
36+
{ label: '即将过期', value: 1 },
37+
{ label: '已过期', value: 2 }
38+
]

src/views/crm/backlog/index.vue

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@
55
<div
66
v-for="(item, index) in leftSides"
77
:key="index"
8-
:class="leftType == item.infoType ? 'side-item-select' : 'side-item-default'"
8+
:class="leftMenu == item.menu ? 'side-item-select' : 'side-item-default'"
99
class="side-item"
1010
@click="sideClick(item)"
1111
>
1212
{{ item.name }}
13-
<el-badge v-if="item.msgCount > 0" :max="99" :value="item.msgCount" />
13+
<el-badge v-if="item.count > 0" :max="99" :value="item.count" />
1414
</div>
1515
</div>
1616
</el-col>
1717
<el-col :span="20" :xs="24">
18-
<TodayCustomer v-if="leftType === 'todayCustomer'" />
19-
<FollowLeads v-if="leftType === 'followLeads'" />
20-
<CheckContract v-if="leftType === 'checkContract'" />
21-
<CheckReceivables v-if="leftType === 'checkReceivables'" />
22-
<EndContract v-if="leftType === 'endContract'" />
23-
<FollowCustomer v-if="leftType === 'followCustomer'" />
24-
<PutInPoolRemind v-if="leftType === 'putInPoolRemind'" />
25-
<RemindReceivables v-if="leftType === 'remindReceivables'" />
18+
<TodayCustomer v-if="leftMenu === 'todayCustomer'" />
19+
<ClueFollowList v-if="leftMenu === 'clueFollow'" />
20+
<CheckContract v-if="leftMenu === 'checkContract'" />
21+
<CheckReceivables v-if="leftMenu === 'checkReceivables'" />
22+
<EndContract v-if="leftMenu === 'endContract'" />
23+
<FollowCustomer v-if="leftMenu === 'followCustomer'" />
24+
<PutInPoolRemind v-if="leftMenu === 'putInPoolRemind'" />
25+
<RemindReceivables v-if="leftMenu === 'remindReceivables'" />
2626
</el-col>
2727
</el-row>
2828
</template>
@@ -33,15 +33,18 @@ import CheckContract from './tables/CheckContract.vue'
3333
import CheckReceivables from './tables/CheckReceivables.vue'
3434
import EndContract from './tables/EndContract.vue'
3535
import FollowCustomer from './tables/FollowCustomer.vue'
36-
import FollowLeads from './tables/FollowLeads.vue'
36+
import ClueFollowList from './components/ClueFollowList.vue'
3737
import PutInPoolRemind from './tables/PutInPoolRemind.vue'
3838
import RemindReceivables from './tables/RemindReceivables.vue'
3939
import TodayCustomer from './tables/TodayCustomer.vue'
40+
import * as ClueApi from '@/api/crm/clue'
4041
41-
const leftType = ref('todayCustomer')
42+
defineOptions({ name: 'CrmBacklog' })
43+
44+
const leftMenu = ref('todayCustomer')
4245
4346
const todayCustomerCountRef = ref(0)
44-
const followLeadsCountRef = ref(0)
47+
const clueFollowCount = ref(0)
4548
const followCustomerCountRef = ref(0)
4649
const putInPoolCustomerRemindCountRef = ref(0)
4750
const checkContractCountRef = ref(0)
@@ -52,61 +55,75 @@ const endContractCountRef = ref(0)
5255
const leftSides = ref([
5356
{
5457
name: '今日需联系客户',
55-
infoType: 'todayCustomer',
56-
msgCount: todayCustomerCountRef
58+
menu: 'todayCustomer',
59+
count: todayCustomerCountRef
5760
},
5861
{
5962
name: '分配给我的线索',
60-
infoType: 'followLeads',
61-
msgCount: followLeadsCountRef
63+
menu: 'clueFollow',
64+
count: clueFollowCount
6265
},
6366
{
6467
name: '分配给我的客户',
65-
infoType: 'followCustomer',
66-
msgCount: followCustomerCountRef
68+
menu: 'followCustomer',
69+
count: followCustomerCountRef
6770
},
6871
{
6972
name: '待进入公海的客户',
70-
infoType: 'putInPoolRemind',
71-
msgCount: putInPoolCustomerRemindCountRef
73+
menu: 'putInPoolRemind',
74+
count: putInPoolCustomerRemindCountRef
7275
},
7376
{
7477
name: '待审核合同',
75-
infoType: 'checkContract',
76-
msgCount: checkContractCountRef
78+
menu: 'checkContract',
79+
count: checkContractCountRef
7780
},
7881
{
7982
name: '待审核回款',
80-
infoType: 'checkReceivables',
81-
msgCount: checkReceivablesCountRef
83+
menu: 'checkReceivables',
84+
count: checkReceivablesCountRef
8285
},
8386
{
8487
name: '待回款提醒',
85-
infoType: 'remindReceivables',
86-
msgCount: remindReceivablesCountRef
88+
menu: 'remindReceivables',
89+
count: remindReceivablesCountRef
8790
},
8891
{
8992
name: '即将到期的合同',
90-
infoType: 'endContract',
91-
msgCount: endContractCountRef
93+
menu: 'endContract',
94+
count: endContractCountRef
9295
}
9396
])
9497
9598
/** 侧边点击 */
9699
const sideClick = (item: any) => {
97-
leftType.value = item.infoType
100+
leftMenu.value = item.menu
101+
}
102+
103+
const getCount = () => {
104+
BacklogApi.getTodayCustomerCount().then((count) => (todayCustomerCountRef.value = count))
105+
ClueApi.getFollowClueCount().then((count) => (clueFollowCount.value = count))
106+
BacklogApi.getClueFollowListCount().then((count) => (clueFollowCount.value = count))
107+
BacklogApi.getFollowCustomerCount().then((count) => (followCustomerCountRef.value = count))
108+
BacklogApi.getPutInPoolCustomerRemindCount().then(
109+
(count) => (putInPoolCustomerRemindCountRef.value = count)
110+
)
111+
BacklogApi.getCheckContractCount().then((count) => (checkContractCountRef.value = count))
112+
BacklogApi.getCheckReceivablesCount().then((count) => (checkReceivablesCountRef.value = count))
113+
BacklogApi.getRemindReceivablePlanCount().then(
114+
(count) => (remindReceivablesCountRef.value = count)
115+
)
116+
BacklogApi.getEndContractCount().then((count) => (endContractCountRef.value = count))
98117
}
99118
100-
/** 加载时读取待办数量 */
119+
/** 激活时 */
120+
onActivated(async () => {
121+
getCount()
122+
})
123+
124+
/** 初始化 */
101125
onMounted(async () => {
102-
BacklogApi.getTodayCustomerCount().then(count => todayCustomerCountRef.value = count)
103-
BacklogApi.getFollowLeadsCount().then(count => followLeadsCountRef.value = count)
104-
BacklogApi.getFollowCustomerCount().then(count => followCustomerCountRef.value = count)
105-
BacklogApi.getPutInPoolCustomerRemindCount().then(count => putInPoolCustomerRemindCountRef.value = count)
106-
BacklogApi.getCheckContractCount().then(count => checkContractCountRef.value = count)
107-
BacklogApi.getCheckReceivablesCount().then(count => checkReceivablesCountRef.value = count)
108-
BacklogApi.getRemindReceivablePlanCount().then(count => remindReceivablesCountRef.value = count)
109-
BacklogApi.getEndContractCount().then(count => endContractCountRef.value = count)
126+
getCount()
110127
})
111128
</script>
112129

src/views/crm/clue/detail/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
>
1919
转化为客户
2020
</el-button>
21-
<el-button type="success" disabled>已转化客户</el-button>
21+
<el-button v-else type="success" disabled>已转化客户</el-button>
2222
</ClueDetailsHeader>
2323
<el-col>
2424
<el-tabs>
@@ -97,7 +97,7 @@ const transfer = () => {
9797
/** 转化为客户 */
9898
const handleTransform = async () => {
9999
await message.confirm(`确定将【${clue.value.name}】转化为客户吗?`)
100-
await ClueApi.transformClue([clueId.value])
100+
await ClueApi.transformClue(clueId.value)
101101
message.success(`转化客户【${clue.value.name}】成功`)
102102
await getClue()
103103
}

0 commit comments

Comments
 (0)