# Conflicts:
#	src/views/crm/backlog/tables/TodayCustomer.vue
This commit is contained in:
YunaiV
2024-01-22 09:45:23 +08:00
14 changed files with 437 additions and 117 deletions

View File

@ -0,0 +1,146 @@
<template>
<el-row :gutter="20">
<el-col :span="4" class="min-w-[200px]">
<div class="side-item-list">
<div
v-for="(item, index) in leftSides"
:key="index"
:class="leftType == item.infoType ? '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.msgCount" />
</div>
</div>
</el-col>
<el-col :span="20" :xs="24">
<TodayCustomer v-if="leftType === 'todayCustomer'" />
<FollowLeads v-if="leftType === 'followLeads'" />
<CheckContract v-if="leftType === 'checkContract'" />
<CheckReceivables v-if="leftType === 'checkReceivables'" />
<EndContract v-if="leftType === 'endContract'" />
<FollowCustomer v-if="leftType === 'followCustomer'" />
<PutInPoolRemind v-if="leftType === 'putInPoolRemind'" />
<RemindReceivables v-if="leftType === 'remindReceivables'" />
</el-col>
</el-row>
</template>
<script lang="ts" setup>
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 PutInPoolRemind from './tables/PutInPoolRemind.vue'
import RemindReceivables from './tables/RemindReceivables.vue'
import TodayCustomer from './tables/TodayCustomer.vue'
const leftType = ref('todayCustomer')
const leftSides = ref([
{
name: '今日需联系客户',
infoType: 'todayCustomer',
msgCount: 1,
tips: '下次跟进时间为今日的客户'
},
{
name: '分配给我的线索',
infoType: 'followLeads',
msgCount: 0,
tips: '转移之后未跟进的线索'
},
{
name: '分配给我的客户',
infoType: 'followCustomer',
msgCount: 0,
tips: '转移、领取、分配之后未跟进的客户,默认显示自己负责的客户'
},
{
name: '待进入公海的客户',
infoType: 'putInPoolRemind',
msgCount: 0,
tips: ''
},
{
name: '待审核合同',
infoType: 'checkContract',
msgCount: 0,
tips: ''
},
{
name: '待审核回款',
crmType: 'receivables',
infoType: 'checkReceivables',
msgCount: 0,
tips: ''
},
{
name: '待回款提醒',
infoType: 'remindReceivables',
msgCount: 4,
tips: ''
},
{
name: '即将到期的合同',
infoType: 'endContract',
msgCount: 20,
tips: '根据“合同到期时间”及设置的“提前提醒天数”提醒'
}
])
/**
* 侧边点击
*/
const sideClick = (item) => {
leftType.value = item.infoType
}
</script>
<style lang="scss" scoped>
.side-item-list {
top: 0;
bottom: 0;
left: 0;
z-index: 1;
font-size: 14px;
background-color: white;
border: 1px solid #e6e6e6;
border-radius: 5px;
.side-item {
position: relative;
height: 50px;
padding: 0 20px;
line-height: 50px;
cursor: pointer;
i {
color: #999;
}
}
}
.side-item-default {
color: #333;
border-right: 2px solid transparent;
}
.side-item-select {
color: #409eff;
background-color: #ecf5ff;
border-right: 2px solid var(--el-color-primary);
}
.el-badge :deep(.el-badge__content) {
top: 0;
border: none;
}
.el-badge {
position: absolute;
top: 0;
right: 15px;
}
</style>

View File

@ -0,0 +1,15 @@
<!-- 待审核合同 -->
<!-- TODO: 后续再统一改名字 -->
<template>
<div>
TODO: 待审核合同
</div>
</template>
<script setup lang="ts" name="CheckContract">
</script>
<style scoped>
</style>

View File

@ -0,0 +1,15 @@
<!-- 待审核回款 -->
<!-- TODO: 后续再统一改名字 -->
<template>
<div>
TODO: 待审核回款
</div>
</template>
<script setup lang="ts" name="CheckReceivables">
</script>
<style scoped>
</style>

View File

@ -0,0 +1,15 @@
<!-- 分配给我的客户 -->
<!-- TODO: 即将到期的合同 -->
<template>
<div>
TODO: 即将到期的合同
</div>
</template>
<script setup lang="ts" name="EndContract">
</script>
<style scoped>
</style>

View File

@ -0,0 +1,160 @@
<!-- 分配给我的客户 -->
<!-- WHERE followUpStatus = ? -->
<template>
<ContentWrap>
<div class="pb-5 text-xl">分配给我的客户</div>
<!-- 搜索工作栏 -->
<el-form
ref="queryFormRef"
:inline="true"
:model="queryParams"
class="-mb-15px"
label-width="68px"
>
<el-form-item label="状态" prop="followUpStatus">
<el-select
v-model="queryParams.followUpStatus"
class="!w-240px"
placeholder="状态"
@change="handleQuery"
>
<el-option
v-for="(option, index) in FOLLOWUP_STATUS"
:label="option.label"
:value="option.value"
:key="index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" label="编号" prop="id" />
<el-table-column align="center" label="客户名称" prop="name" width="160">
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="手机" prop="mobile" width="120" />
<el-table-column align="center" label="电话" prop="telephone" width="120" />
<el-table-column align="center" label="客户来源" prop="source" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_SOURCE" :value="scope.row.source" />
</template>
</el-table-column>
<el-table-column align="center" label="所属行业" prop="industryId" width="120">
<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="120">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_LEVEL" :value="scope.row.level" />
</template>
</el-table-column>
<el-table-column align="center" label="网址" prop="website" width="200" />
<el-table-column
:formatter="dateFormatter"
align="center"
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column align="center" label="成交状态" prop="dealStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" />
</template>
</el-table-column>
<el-table-column align="center" label="距离进入公海" prop="poolDay">
<template #default="scope"> {{ scope.row.poolDay }} </template>
</el-table-column>
<el-table-column
:formatter="dateFormatter"
align="center"
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="updateTime"
width="180px"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNo"
:total="total"
@pagination="getList"
/>
</ContentWrap>
</template>
<script setup lang="ts" name="FollowCustomer">
import * as CustomerApi from '@/api/crm/customer'
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { FOLLOWUP_STATUS } from './common'
const { push } = useRouter()
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = ref({
pageNo: 1,
pageSize: 10,
followUpStatus: false,
sceneType: 1
})
const queryFormRef = ref() // 搜索的表单
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await CustomerApi.getCustomerPage(queryParams.value)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNo = 1
getList()
}
/** 打开客户详情 */
const openDetail = (id: number) => {
push({ name: 'CrmCustomerDetail', params: { id } })
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
<style scoped></style>

View File

@ -0,0 +1,125 @@
<!-- TODO: dhb52 待Clue页面更新后同步更新 -->
<!-- WHERE transformStatus = 0 AND followUpStatus = ? -->
<template>
<ContentWrap>
<div class="pb-5 text-xl">分配给我的线索</div>
<!-- 搜索工作栏 -->
<el-form
ref="queryFormRef"
:inline="true"
:model="queryParams"
class="-mb-15px"
label-width="68px"
>
<el-form-item label="状态" prop="followUpStatus">
<el-select
v-model="queryParams.followUpStatus"
class="!w-240px"
placeholder="状态"
@change="handleQuery"
>
<el-option
v-for="(option, index) in FOLLOWUP_STATUS"
:label="option.label"
:value="option.value"
:key="index"
/>
</el-select>
</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="转化状态" align="center" prop="transformStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.transformStatus" />
</template>
</el-table-column>
<el-table-column label="跟进状态" align="center" prop="followUpStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.followUpStatus" />
</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="下次联系时间"
align="center"
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
label="最后跟进时间"
align="center"
prop="contactLastTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<script setup lang="ts" name="FollowLeads">
import * as ClueApi from '@/api/crm/clue'
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { FOLLOWUP_STATUS } from './common'
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
followUpStatus: false,
transformStatus: false // 固定为【未转移】
})
const queryFormRef = ref() // 搜索的表单
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await ClueApi.getCluePage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
<style scoped></style>

View File

@ -0,0 +1,15 @@
<!-- 待进入公海的客户 -->
<!-- TODO: 后续再统一改名字 -->
<template>
<div>
TODO: 待进入公海的客户
</div>
</template>
<script setup lang="ts" name="PutInPoolRemind">
</script>
<style scoped>
</style>

View File

@ -0,0 +1,15 @@
<!-- 待回款提醒 -->
<!-- TODO: 后续再统一改名字 -->
<template>
<div>
TODO: 待回款提醒
</div>
</template>
<script setup lang="ts" name="RemindReceivables">
</script>
<style scoped>
</style>

View File

@ -0,0 +1,169 @@
<template>
<ContentWrap>
<div class="pb-5 text-xl"> 今日需联系客户 </div>
<!-- 搜索工作栏 -->
<el-form
ref="queryFormRef"
:inline="true"
:model="queryParams"
class="-mb-15px"
label-width="68px"
>
<el-form-item label="状态" prop="contactStatus">
<el-select
v-model="queryParams.contactStatus"
class="!w-240px"
placeholder="状态"
@change="handleQuery"
>
<el-option
v-for="(option, index) in CONTACT_STATUS"
:label="option.label"
:value="option.value"
:key="index"
/>
</el-select>
</el-form-item>
<el-form-item label="归属" prop="sceneType">
<el-select
v-model="queryParams.sceneType"
class="!w-240px"
placeholder="归属"
@change="handleQuery"
>
<el-option
v-for="(option, index) in SCENE_TYPES"
:label="option.label"
:value="option.value"
:key="index"
/>
</el-select>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" label="编号" prop="id" />
<el-table-column align="center" label="客户名称" prop="name" width="160">
<template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column align="center" label="手机" prop="mobile" width="120" />
<el-table-column align="center" label="电话" prop="telephone" width="120" />
<el-table-column align="center" label="客户来源" prop="source" width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_SOURCE" :value="scope.row.source" />
</template>
</el-table-column>
<el-table-column align="center" label="所属行业" prop="industryId" width="120">
<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="120">
<template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_LEVEL" :value="scope.row.level" />
</template>
</el-table-column>
<el-table-column align="center" label="网址" prop="website" width="200" />
<el-table-column
:formatter="dateFormatter"
align="center"
label="下次联系时间"
prop="contactNextTime"
width="180px"
/>
<el-table-column align="center" label="备注" prop="remark" width="200" />
<el-table-column align="center" label="成交状态" prop="dealStatus">
<template #default="scope">
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="scope.row.dealStatus" />
</template>
</el-table-column>
<el-table-column align="center" label="距进入公海天数" prop="poolDay" width="100px" />
<el-table-column
:formatter="dateFormatter"
align="center"
label="最后跟进时间"
prop="contactLastTime"
width="180px"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="updateTime"
width="180px"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="创建时间"
prop="createTime"
width="180px"
/>
<el-table-column align="center" label="负责人" prop="ownerUserName" width="100px" />
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="100px" />
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNo"
:total="total"
@pagination="getList"
/>
</ContentWrap>
</template>
<script lang="ts" setup name="TodayCustomer">
import * as BacklogApi from '@/api/crm/backlog'
import { DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { CONTACT_STATUS, SCENE_TYPES } from './common'
const { push } = useRouter()
const loading = ref(true) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 列表的数据
const queryParams = ref({
pageNo: 1,
pageSize: 10,
contactStatus: 1,
sceneType: 1
})
const queryFormRef = ref() // 搜索的表单
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await BacklogApi.getTodayCustomerPage(queryParams.value)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNo = 1
getList()
}
/** 打开客户详情 */
const openDetail = (id: number) => {
push({ name: 'CrmCustomerDetail', params: { id } })
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>
<style lang="scss"></style>

View File

@ -0,0 +1,19 @@
/** 跟进状态 */
export const FOLLOWUP_STATUS = [
{ label: '已跟进', value: true },
{ label: '待跟进', value: false }
]
/** 归属范围 */
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 }
]