📖 CRM:线索的跟进逻辑
This commit is contained in:
parent
0ae6139e92
commit
04a42bc6d4
@ -6,11 +6,6 @@ export const getTodayCustomerCount = async () => {
|
|||||||
return await request.get({ url: '/crm/customer/today-customer-count' })
|
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. 获得分配给我的客户数量
|
// 3. 获得分配给我的客户数量
|
||||||
export const getFollowCustomerCount = async () => {
|
export const getFollowCustomerCount = async () => {
|
||||||
return await request.get({ url: '/crm/customer/follow-customer-count' })
|
return await request.get({ url: '/crm/customer/follow-customer-count' })
|
||||||
|
@ -68,6 +68,11 @@ export const transferClue = async (data: TransferReqVO) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 线索转化为客户
|
// 线索转化为客户
|
||||||
export const transformClue = async (ids: number[]) => {
|
export const transformClue = async (id: number) => {
|
||||||
return await request.put({ url: '/crm/clue/transform?ids=' + ids.join(',') })
|
return await request.put({ url: '/crm/clue/transform', params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得分配给我的、待跟进的线索数量
|
||||||
|
export const getFollowClueCount = async () => {
|
||||||
|
return await request.get({ url: '/crm/clue/follow-count' })
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
<!-- TODO: dhb52 待Clue页面更新后同步更新 -->
|
|
||||||
<!-- WHERE transformStatus = 0 AND followUpStatus = ? -->
|
|
||||||
<template>
|
<template>
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<div class="pb-5 text-xl">分配给我的线索</div>
|
<div class="pb-5 text-xl">分配给我的线索</div>
|
||||||
@ -31,30 +29,40 @@
|
|||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<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 label="编号" align="center" prop="id" />
|
<el-table-column label="线索名称" align="center" prop="name" fixed="left" width="120">
|
||||||
<el-table-column label="转化状态" align="center" prop="transformStatus">
|
|
||||||
<template #default="scope">
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="跟进状态" align="center" prop="followUpStatus">
|
<el-table-column label="线索来源" align="center" prop="source" width="100">
|
||||||
<template #default="scope">
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="线索名称" align="center" prop="name" />
|
|
||||||
<el-table-column label="客户id" align="center" prop="customerId" />
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="下次联系时间"
|
|
||||||
align="center"
|
|
||||||
prop="contactNextTime"
|
|
||||||
:formatter="dateFormatter"
|
:formatter="dateFormatter"
|
||||||
|
align="center"
|
||||||
|
label="下次联系时间"
|
||||||
|
prop="contactNextTime"
|
||||||
width="180px"
|
width="180px"
|
||||||
/>
|
/>
|
||||||
<el-table-column label="电话" align="center" prop="telephone" />
|
<el-table-column align="center" label="备注" prop="remark" width="200" />
|
||||||
<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
|
<el-table-column
|
||||||
label="最后跟进时间"
|
label="最后跟进时间"
|
||||||
align="center"
|
align="center"
|
||||||
@ -62,7 +70,16 @@
|
|||||||
:formatter="dateFormatter"
|
:formatter="dateFormatter"
|
||||||
width="180px"
|
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
|
<el-table-column
|
||||||
label="创建时间"
|
label="创建时间"
|
||||||
align="center"
|
align="center"
|
||||||
@ -70,6 +87,7 @@
|
|||||||
:formatter="dateFormatter"
|
:formatter="dateFormatter"
|
||||||
width="180px"
|
width="180px"
|
||||||
/>
|
/>
|
||||||
|
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
|
||||||
</el-table>
|
</el-table>
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
<Pagination
|
<Pagination
|
||||||
@ -80,13 +98,14 @@
|
|||||||
/>
|
/>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
<script setup lang="ts" name="FollowLeads">
|
|
||||||
import * as ClueApi from '@/api/crm/clue'
|
import * as ClueApi from '@/api/crm/clue'
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
import { DICT_TYPE } from '@/utils/dict'
|
||||||
import { dateFormatter } from '@/utils/formatTime'
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
import { FOLLOWUP_STATUS } from './common'
|
import { FOLLOWUP_STATUS } from './common'
|
||||||
|
|
||||||
|
defineOptions({ name: 'CrmClueFollowList' })
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
const total = ref(0) // 列表的总页数
|
const total = ref(0) // 列表的总页数
|
||||||
const list = ref([]) // 列表的数据
|
const list = ref([]) // 列表的数据
|
||||||
@ -94,7 +113,7 @@ const queryParams = reactive({
|
|||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
followUpStatus: false,
|
followUpStatus: false,
|
||||||
transformStatus: false // 固定为【未转移】
|
transformStatus: false
|
||||||
})
|
})
|
||||||
const queryFormRef = ref() // 搜索的表单
|
const queryFormRef = ref() // 搜索的表单
|
||||||
|
|
||||||
@ -116,10 +135,19 @@ const handleQuery = () => {
|
|||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 打开线索详情 */
|
||||||
|
const { push } = useRouter()
|
||||||
|
const openDetail = (id: number) => {
|
||||||
|
push({ name: 'CrmClueDetail', params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 激活时 */
|
||||||
|
onActivated(async () => {
|
||||||
|
await getList()
|
||||||
|
})
|
||||||
|
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
|
38
src/views/crm/backlog/components/common.ts
Normal file
38
src/views/crm/backlog/components/common.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/** 跟进状态 */
|
||||||
|
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 }
|
||||||
|
]
|
@ -5,24 +5,24 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(item, index) in leftSides"
|
v-for="(item, index) in leftSides"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="leftType == item.infoType ? 'side-item-select' : 'side-item-default'"
|
:class="leftMenu == item.menu ? 'side-item-select' : 'side-item-default'"
|
||||||
class="side-item"
|
class="side-item"
|
||||||
@click="sideClick(item)"
|
@click="sideClick(item)"
|
||||||
>
|
>
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
<el-badge v-if="item.msgCount > 0" :max="99" :value="item.msgCount" />
|
<el-badge v-if="item.count > 0" :max="99" :value="item.count" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="20" :xs="24">
|
<el-col :span="20" :xs="24">
|
||||||
<TodayCustomer v-if="leftType === 'todayCustomer'" />
|
<TodayCustomer v-if="leftMenu === 'todayCustomer'" />
|
||||||
<FollowLeads v-if="leftType === 'followLeads'" />
|
<ClueFollowList v-if="leftMenu === 'clueFollow'" />
|
||||||
<CheckContract v-if="leftType === 'checkContract'" />
|
<CheckContract v-if="leftMenu === 'checkContract'" />
|
||||||
<CheckReceivables v-if="leftType === 'checkReceivables'" />
|
<CheckReceivables v-if="leftMenu === 'checkReceivables'" />
|
||||||
<EndContract v-if="leftType === 'endContract'" />
|
<EndContract v-if="leftMenu === 'endContract'" />
|
||||||
<FollowCustomer v-if="leftType === 'followCustomer'" />
|
<FollowCustomer v-if="leftMenu === 'followCustomer'" />
|
||||||
<PutInPoolRemind v-if="leftType === 'putInPoolRemind'" />
|
<PutInPoolRemind v-if="leftMenu === 'putInPoolRemind'" />
|
||||||
<RemindReceivables v-if="leftType === 'remindReceivables'" />
|
<RemindReceivables v-if="leftMenu === 'remindReceivables'" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -33,15 +33,18 @@ import CheckContract from './tables/CheckContract.vue'
|
|||||||
import CheckReceivables from './tables/CheckReceivables.vue'
|
import CheckReceivables from './tables/CheckReceivables.vue'
|
||||||
import EndContract from './tables/EndContract.vue'
|
import EndContract from './tables/EndContract.vue'
|
||||||
import FollowCustomer from './tables/FollowCustomer.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 PutInPoolRemind from './tables/PutInPoolRemind.vue'
|
||||||
import RemindReceivables from './tables/RemindReceivables.vue'
|
import RemindReceivables from './tables/RemindReceivables.vue'
|
||||||
import TodayCustomer from './tables/TodayCustomer.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 todayCustomerCountRef = ref(0)
|
||||||
const followLeadsCountRef = ref(0)
|
const clueFollowCount = ref(0)
|
||||||
const followCustomerCountRef = ref(0)
|
const followCustomerCountRef = ref(0)
|
||||||
const putInPoolCustomerRemindCountRef = ref(0)
|
const putInPoolCustomerRemindCountRef = ref(0)
|
||||||
const checkContractCountRef = ref(0)
|
const checkContractCountRef = ref(0)
|
||||||
@ -52,61 +55,75 @@ const endContractCountRef = ref(0)
|
|||||||
const leftSides = ref([
|
const leftSides = ref([
|
||||||
{
|
{
|
||||||
name: '今日需联系客户',
|
name: '今日需联系客户',
|
||||||
infoType: 'todayCustomer',
|
menu: 'todayCustomer',
|
||||||
msgCount: todayCustomerCountRef
|
count: todayCustomerCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '分配给我的线索',
|
name: '分配给我的线索',
|
||||||
infoType: 'followLeads',
|
menu: 'clueFollow',
|
||||||
msgCount: followLeadsCountRef
|
count: clueFollowCount
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '分配给我的客户',
|
name: '分配给我的客户',
|
||||||
infoType: 'followCustomer',
|
menu: 'followCustomer',
|
||||||
msgCount: followCustomerCountRef
|
count: followCustomerCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '待进入公海的客户',
|
name: '待进入公海的客户',
|
||||||
infoType: 'putInPoolRemind',
|
menu: 'putInPoolRemind',
|
||||||
msgCount: putInPoolCustomerRemindCountRef
|
count: putInPoolCustomerRemindCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '待审核合同',
|
name: '待审核合同',
|
||||||
infoType: 'checkContract',
|
menu: 'checkContract',
|
||||||
msgCount: checkContractCountRef
|
count: checkContractCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '待审核回款',
|
name: '待审核回款',
|
||||||
infoType: 'checkReceivables',
|
menu: 'checkReceivables',
|
||||||
msgCount: checkReceivablesCountRef
|
count: checkReceivablesCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '待回款提醒',
|
name: '待回款提醒',
|
||||||
infoType: 'remindReceivables',
|
menu: 'remindReceivables',
|
||||||
msgCount: remindReceivablesCountRef
|
count: remindReceivablesCountRef
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '即将到期的合同',
|
name: '即将到期的合同',
|
||||||
infoType: 'endContract',
|
menu: 'endContract',
|
||||||
msgCount: endContractCountRef
|
count: endContractCountRef
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
/** 侧边点击 */
|
/** 侧边点击 */
|
||||||
const sideClick = (item: any) => {
|
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 () => {
|
onMounted(async () => {
|
||||||
BacklogApi.getTodayCustomerCount().then(count => todayCustomerCountRef.value = count)
|
getCount()
|
||||||
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)
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
>
|
>
|
||||||
转化为客户
|
转化为客户
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="success" disabled>已转化客户</el-button>
|
<el-button v-else type="success" disabled>已转化客户</el-button>
|
||||||
</ClueDetailsHeader>
|
</ClueDetailsHeader>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-tabs>
|
<el-tabs>
|
||||||
@ -97,7 +97,7 @@ const transfer = () => {
|
|||||||
/** 转化为客户 */
|
/** 转化为客户 */
|
||||||
const handleTransform = async () => {
|
const handleTransform = async () => {
|
||||||
await message.confirm(`确定将【${clue.value.name}】转化为客户吗?`)
|
await message.confirm(`确定将【${clue.value.name}】转化为客户吗?`)
|
||||||
await ClueApi.transformClue([clueId.value])
|
await ClueApi.transformClue(clueId.value)
|
||||||
message.success(`转化客户【${clue.value.name}】成功`)
|
message.success(`转化客户【${clue.value.name}】成功`)
|
||||||
await getClue()
|
await getClue()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user