【招生平台用户端】 新增# 线索管理:详情处理

main
kaeery 2025-02-28 10:09:09 +08:00
parent 8cf9f6e0ea
commit 04760b070f
8 changed files with 127 additions and 66 deletions

View File

@ -28,3 +28,36 @@ export const conversionMap = {
[converStatusEnum.CONVERTED]: '已成交',
[converStatusEnum.FAILED]: '已战败'
}
export const conversionOptions = [
{ label: '待领取', value: converStatusEnum.UN_RECEIVED },
{ label: '转化中', value: converStatusEnum.CONVERTED_PROCESS },
{ label: '已添加', value: converStatusEnum.ADD_RELATION },
{ label: '异常待处理', value: converStatusEnum.EXCEPTION },
{ label: '已成交', value: converStatusEnum.CONVERTED },
{ label: '已战败', value: converStatusEnum.FAILED }
]
export enum CluseSourceEnum {
OFFLINE_LIST = 0
}
export const ClueSourceMap = {
[CluseSourceEnum.OFFLINE_LIST]: '线下列表'
}
export enum stateEnum {
ADD_RELATION = 0, //账号已添加
NO_EXIST = 1, //账号不存在
UN_PASS = 2 //账号未通过
}
export const stateMap: Record<stateEnum, string> = {
[stateEnum.ADD_RELATION]: '账号已添加',
[stateEnum.NO_EXIST]: '账号不存在',
[stateEnum.UN_PASS]: '账号未通过'
}
export enum ConverSuccessEnum {
YES = 1,
NO = 0
}
export const conversitionMap: Record<ConverSuccessEnum, string> = {
[ConverSuccessEnum.YES]: '是',
[ConverSuccessEnum.NO]: '否'
}

View File

@ -9,6 +9,7 @@
--color-white: #ffffff;
--color-red: #d9001b;
--color-green: #00b42a;
--color-green2: #baf114;
--table-header-bg-color: #f8f8f8;
--el-font-size-extra-large: 18px;
--el-menu-base-level-padding: 16px;
@ -50,4 +51,5 @@
--el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.12);
--el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.12);
--el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.08), 0px 12px 32px rgba(0, 0, 0, 0.12), 0px 8px 16px -8px rgba(0, 0, 0, 0.16);
--color-purple: '#800080';
}

View File

@ -1,19 +1,80 @@
<template>
<el-space direction="vertical" alignment="normal" :size="24" v-loading="loading">
<el-space style="width: 100%" direction="vertical" alignment="normal" :size="24" v-loading="loading">
<el-descriptions v-for="item in baseInfo" :key="item.title" :title="item.title" direction="vertical" :column="4" border>
<el-descriptions-item v-for="(itemy, indey) in item.data" :key="indey" :label="itemy.label">{{ itemy.value }}</el-descriptions-item>
<el-descriptions-item v-for="(itemy, indey) in item.data" :key="indey" :label="itemy.label">
<span v-if="itemy.custom">{{ formatValue(itemy.field, itemy.value) }}</span>
<span v-else>{{ itemy.value }}</span>
</el-descriptions-item>
</el-descriptions>
</el-space>
</template>
<script setup lang="ts">
import { clueDetail } from '@/api/clue'
import { ClueSourceMap, conversitionMap, stateMap } from '@/enums'
const optionsMap: Record<string, any> = {
listSource: ClueSourceMap,
state: stateMap,
isConversion: conversitionMap
}
const props = defineProps({
modelValue: {
type: String,
default: 'baseInfo'
},
id: {
type: Number
}
})
const loading = ref(false)
const baseInfo = ref<any[]>([])
const formatValue = computed(() => (field: string, value: number) => optionsMap[field][value])
const fetchClueDetail = async () => {
const { id } = props
loading.value = true
try {
const result = await clueDetail({ id })
assemData(result)
} catch (error) {}
loading.value = false
}
//
const assemData = (result: any) => {
type ClueBaseInfoKeys = keyof typeof clueBaseInfo
const clueBaseInfo = {
线索基本信息: { listSource: '线索来源', studentName: '学生名字', phone: '联系电话', basicInformation: '基本情况' },
电销信息: { telemarketingTeacherName: '负责人', telemarketingOrganization: '所属组织', state: '线索状态', followUpTime: '跟进时间' },
招生信息: {
recruitTeacherName: '负责人',
recruitOrganization: '所属组织',
state: '线索状态',
getTime: '领取时间',
isConversion: '是否转化成功',
remark: '备注',
updateTime: '成交时间'
}
}
Object.keys(clueBaseInfo).forEach((key: ClueBaseInfoKeys) => {
const data = clueBaseInfo[key]
const list = Object.keys(data).map(item => {
const value = result[item]
return {
label: data[item],
value,
custom: ['listSource', 'state', 'isConversion'].includes(item),
field: item
}
})
baseInfo.value.push({
title: key,
data: list
})
})
}
watch(
() => props.modelValue,
() => {
@ -21,49 +82,5 @@ watch(
},
{ immediate: true }
)
const fetchClueDetail = () => {
loading.value = true
try {
} catch (error) {}
loading.value = false
}
const baseInfo = ref([
{
title: '线索基本信息',
data: [
{ label: '线索提供者', value: '张三' },
{ label: '线索来源', value: '线下名单' },
{ label: '创建人', value: 'admin' },
{ label: '创建时间', value: '2025-02-12 11:30:00' },
{ label: '客户姓名', value: '韩梅梅' },
{ label: '联系电话', value: '18866668888' },
{
label: '基本情况',
value: '学生爸爸接电话学生高三毕业300多分家长不清楚学生收到录取通知家长说学生不读书了我让家长先问问学生对未来的规划先和学生沟通一下家长同意我们加他微信发专业资料给他看看可以在微信上问问学生具体情况。推荐3+2给家长发一下学校简介和专业资料。'
}
]
},
{
title: '电销信息',
data: [
{ label: '负责人', value: '张三' },
{ label: '所属组织', value: '广州团队-A组' },
{ label: '线索状态', value: '已添加' },
{ label: '跟进时间', value: '2025-02-12 11:30:00' }
]
},
{
title: '招生信息',
data: [
{ label: '负责人', value: '张三' },
{ label: '所属组织', value: '广州团队-A组' },
{ label: '领取时间', value: '2025-02-12 11:19:00' },
{ label: '状态', value: '账号已添加' },
{ label: '是否转化成功', value: '' },
{ label: '备注', value: '' },
{ label: '成交时间', value: '' }
]
}
])
</script>
<style scoped></style>

View File

@ -3,7 +3,7 @@
<search-form v-model="queryParams" @reset-page="resetPage" @reset-params="resetParams" />
<clue-list :loading="pager.loading" :tableData="pager.lists">
<template #operation="{ row }">
<el-button type="primary" link @click="handleDetail(row)"></el-button>
<el-button type="primary" link @click="handleDetail(row.id)"></el-button>
</template>
</clue-list>
</div>
@ -29,9 +29,10 @@ const { pager, getLists, resetPage, resetParams } = usePaging({
getLists()
const clueDetailRef = ref()
const handleDetail = () => {
const handleDetail = (id: number) => {
clueDetailRef.value.openDrawer({
title: '线索详情'
title: '线索详情',
data: { id }
})
}
</script>

View File

@ -2,7 +2,7 @@
<ProDrawer ref="proDrawerRef">
<el-tabs v-model="activeTab">
<el-tab-pane v-for="tab in tabs" :key="tab.name" :label="tab.label" :name="tab.name">
<component v-if="tab.name == activeTab" :is="tab.component" v-model="activeTab" />
<component v-if="tab.name == activeTab" :is="tab.component" v-model="activeTab" :id="clueId" />
</el-tab-pane>
</el-tabs>
</ProDrawer>
@ -17,9 +17,11 @@ const proDrawerRef = ref<InstanceType<typeof ProDrawer>>()
const activeTab = ref('baseInfo')
const tabs = shallowRef([
{ label: '基础信息', name: 'baseInfo', component: baseIfno },
{ label: '线索来源', name: 'clueRecord', component: clueRecord }
{ label: '线索记录', name: 'clueRecord', component: clueRecord }
])
const clueId = ref()
const openDrawer = (params: IParams) => {
clueId.value = params.data.id
proDrawerRef.value?.openDrawer(params)
}
defineExpose({

View File

@ -5,7 +5,10 @@
<span>{{ parseClueSource(row.listSource) }}</span>
</template>
<template #situation="{ row }">
<div class="flex items-center gap-2">
<span class="w-[6px] h-[6px] rounded-[3px]" :class="conversionStyle[row.situation]"></span>
<span>{{ parseConversion(row.situation) }}</span>
</div>
</template>
<template #operation="{ row }">
<slot name="operation" :row="row" />
@ -17,6 +20,14 @@
<script setup lang="ts">
import { converStatusEnum, conversionMap } from '@/enums'
const conversionStyle: Record<number, string> = {
[converStatusEnum.UN_RECEIVED]: 'bg-green2',
[converStatusEnum.CONVERTED_PROCESS]: 'bg-primary',
[converStatusEnum.ADD_RELATION]: 'bg-purple',
[converStatusEnum.EXCEPTION]: 'bg-error',
[converStatusEnum.CONVERTED]: 'bg-success',
[converStatusEnum.FAILED]: 'bg-error'
}
defineProps({
loading: {
type: Boolean,

View File

@ -2,10 +2,10 @@
<el-card shadow="never" class="!border-none">
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
<el-form-item label="学生名字">
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.likeWork" clearable @keyup.enter="$emit('resetPage')" />
</el-form-item>
<el-form-item label="转化情况">
<el-select class="w-[280px]" v-model="modelValue.conversionStatus">
<el-select class="w-[280px]" v-model="modelValue.situation">
<el-option v-for="option in conversionOptions" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
@ -18,24 +18,17 @@
</template>
<script setup lang="ts">
import { conversionOptions } from '@/enums'
defineProps({
modelValue: {
type: Object,
default: () => ({
name: '',
conversionStatus: ''
likeWork: '',
situation: ''
})
}
})
defineEmits(['resetPage', 'resetParams'])
const conversionOptions = ref([
{ label: '有意向', value: 1 },
{ label: '待领取', value: 2 },
{ label: '转化中', value: 3 },
{ label: '已添加', value: 4 },
{ label: '异常待处理', value: 5 },
{ label: '已成交', value: 6 },
{ label: '已战败', value: 7 }
])
</script>
<style scoped></style>

View File

@ -36,7 +36,9 @@ module.exports = {
'fill-lighter': 'var(--el-fill-color-lighter)',
mask: 'var(--el-mask-color)',
green: 'var(--color-green)',
black2: 'var(--el-text-color-black2)'
green2: 'var(--color-green2)',
black2: 'var(--el-text-color-black2)',
purple: 'var(--color-purple)'
},
fontFamily: {
sans: ['PingFang SC', 'Arial', 'Hiragino Sans GB', 'Microsoft YaHei', 'sans-serif']