Browse Source

refactor(market): 重构市场线索添加功能

- 将原有单页表单拆分为两步:添加客户和六要素信息- 新增字典数据获取接口和方法
- 优化下拉选择器逻辑,支持动态加载选项
- 重新组织表单验证逻辑,按步骤进行验证
- 更新提交接口和成功后的处理流程
- 调整页面样式和布局,提高用户体验
master
liutong 1 year ago
parent
commit
9e054928a2
  1. 15
      api/apiRoute.js
  2. 749
      pages/market/clue/add_clues.vue
  3. 2
      pages/market/clue/index.vue

15
api/apiRoute.js

@ -38,6 +38,13 @@ export default {
return res; return res;
}) })
}, },
//获取字典数据
common_Dictionary(data = {}) {
let url = '/common/getDictionary'
return http.get(url, data).then(res => {
return res;
})
},
@ -118,12 +125,20 @@ export default {
//↓↓↓↓↓↓↓↓↓↓↓↓-----销售接口相关-----↓↓↓↓↓↓↓↓↓↓↓↓ //↓↓↓↓↓↓↓↓↓↓↓↓-----销售接口相关-----↓↓↓↓↓↓↓↓↓↓↓↓
//修改销售端个人资料
editPersonnel(data = {}) { editPersonnel(data = {}) {
let url = '/personnel/info' let url = '/personnel/info'
return http.get(url, data).then(res => { return http.get(url, data).then(res => {
return res; return res;
}) })
}, },
//销售端
xs_addCustomerResources(data = {}) {
let url = '/customerResources/add'
return http.post(url, data).then(res => {
return res;
})
},

749
pages/market/clue/add_clues.vue

@ -14,12 +14,12 @@
<!-- 添加客户--> <!-- 添加客户-->
<view style="margin-top: 20rpx;" v-if="optionTableId == 0"> <view style="margin-top: 20rpx;" v-if="optionTableId == 0">
<view class="search_box"> <!-- <view class="search_box">-->
<view class="input_box"> <!-- <view class="input_box">-->
<input type="text" v-model="student_name" placeholder="请输入客户名称"> <!-- <input type="text" v-model="student_name" placeholder="请输入客户名称">-->
</view> <!-- </view>-->
<view class="btn" @click="clientList()">查重</view> <!-- <view class="btn" @click="clientList()">查重</view>-->
</view> <!-- </view>-->
<view class="form-style"> <view class="form-style">
<fui-form ref="form" top="0" :model="formData" :show="false"> <fui-form ref="form" top="0" :model="formData" :show="false">
@ -66,6 +66,7 @@
</view> </view>
</fui-form-item> </fui-form-item>
<!--顾问--> <!--顾问-->
<!--
<fui-form-item <fui-form-item
label="顾问" label="顾问"
asterisk asteriskPosition="right" asterisk asteriskPosition="right"
@ -84,6 +85,28 @@
</view> </view>
</view> </view>
</fui-form-item> </fui-form-item>
-->
<fui-form-item
label="顾问"
asterisk asteriskPosition="right"
labelSize='26'
prop="title"
background='#434544'
labelColor='#fff'
:bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<fui-input
:borderBottom="false"
:padding="[0]"
:disabled="true"
placeholder="点击填写"
v-model="picker_config.consultant.text"
backgroundColor="#434544"
size="26"
color="#808080"
></fui-input>
</view>
</fui-form-item>
<!--姓名--> <!--姓名-->
<fui-form-item <fui-form-item
label="姓名" label="姓名"
@ -189,84 +212,6 @@
></fui-input> ></fui-input>
</view> </view>
</fui-form-item> </fui-form-item>
<!--购买力-->
<fui-form-item
label="购买力"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openCicker(`purchasing_power`)">
{{ (formData.purchasing_power) ? picker_config.purchasing_power.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--认知理念-->
<fui-form-item
label="认知理念"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openCicker(`cognitive_idea`)">
{{ (formData.cognitive_idea) ? picker_config.cognitive_idea.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--可选上课时间-->
<fui-form-item
label="可选上课时间"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openDate(`optional_class_time`)">
{{ (formData.optional_class_time) ? formData.optional_class_time : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--距离-->
<fui-form-item
label="距离"
asterisk asteriskPosition="right"
labelSize='26'
prop="title"
background='#434544'
labelColor='#fff'
:bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<fui-input
:borderBottom="false"
:padding="[0]"
placeholder="点击填写"
v-model="formData.distance"
backgroundColor="#434544"
size="26"
color="#fff"
></fui-input>
</view>
</fui-form-item>
<!--决策人--> <!--决策人-->
<fui-form-item <fui-form-item
label="决策人" label="决策人"
@ -307,25 +252,6 @@
</view> </view>
</view> </view>
</fui-form-item> </fui-form-item>
<!--所属校区-->
<fui-form-item
label="所属校区"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openCicker(`campus`)">
{{ (formData.campus) ? picker_config.campus.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--客户状态--> <!--客户状态-->
<fui-form-item <fui-form-item
label="客户状态" label="客户状态"
@ -350,13 +276,141 @@
</view> </view>
<view class="fui-btn__box"> <view class="fui-btn__box">
<fui-button background="#434544" color="#24BA9F" borderColor="#24BA9F" @click="submit">下一步</fui-button> <fui-button background="#434544" color="#24BA9F" borderColor="#24BA9F" @click="nextStep('1')">下一步</fui-button>
</view> </view>
</view> </view>
<!-- 添加六要素--> <!-- 添加六要素-->
<view style="margin-top: 20rpx;" v-if="optionTableId == 1"> <view style="margin-top: 20rpx;" v-if="optionTableId == 1">
六要素 <view class="form-style">
<fui-form ref="form" top="0" :model="formData" :show="false">
<view class="title" style="margin-top: 20rpx;">六要素信息</view>
<view class="input-style">
<!--购买力-->
<fui-form-item
label="购买力"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openCicker(`purchasing_power`)">
{{ (formData.purchasing_power) ? picker_config.purchasing_power.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--认知理念-->
<fui-form-item
label="认知理念"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openCicker(`cognitive_idea`)">
{{ (formData.cognitive_idea) ? picker_config.cognitive_idea.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--可选上课时间-->
<fui-form-item
label="可选上课时间"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openDate(`optional_class_time`)">
{{ (formData.optional_class_time) ? formData.optional_class_time : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--承诺到访时间-->
<fui-form-item
label="承诺到访时间"
asterisk asteriskPosition="right"
labelSize='26'
prop=""
background='#434544'
labelColor='#fff'
:bottomBorder='false'
>
<view class="input-title" style="margin-right:14rpx;">
<view
class="input-title"
style="margin-right:14rpx;"
@click="openDate(`promised_visit_time`)">
{{ (formData.promised_visit_time) ? formData.promised_visit_time : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--距离-->
<fui-form-item
label="距离"
asterisk asteriskPosition="right"
labelSize='26'
prop="title"
background='#434544'
labelColor='#fff'
:bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<fui-input
:borderBottom="false"
:padding="[0]"
placeholder="点击填写"
v-model="formData.distance"
backgroundColor="#434544"
size="26"
color="#fff"
></fui-input>
</view>
</fui-form-item>
<!--沟通备注-->
<fui-form-item
label="沟通备注"
asterisk asteriskPosition="right"
labelSize='26'
prop="title"
background='#434544'
labelColor='#fff'
:bottomBorder='false'>
<view class="input-title" style="margin-right:14rpx;">
<fui-input
:borderBottom="false"
:padding="[0]"
placeholder="点击填写"
v-model="formData.communication"
backgroundColor="#434544"
size="26"
color="#fff"
></fui-input>
</view>
</fui-form-item>
</view>
</fui-form>
</view>
<view class="fui-btn__box">
<fui-button background="#434544" color="#24BA9F" borderColor="#24BA9F" @click="submit">保存</fui-button>
</view>
</view> </view>
@ -451,6 +505,7 @@
</template> </template>
<script> <script>
import apiRoute from '@/api/apiRoute.js';
import commonApi from '@/api/common.js'; import commonApi from '@/api/common.js';
import marketApi from '@/api/market.js'; import marketApi from '@/api/market.js';
import memberApi from '@/api/member.js'; import memberApi from '@/api/member.js';
@ -535,34 +590,25 @@ export default {
formData: { formData: {
// 客户基础信息 // 客户基础信息
source_channel:'',//来源渠道 source_channel:'',//来源渠道
source:'',//来源 source:'',//来源
consultant:'',//顾问 consultant:'',//顾问
name:'',//姓名 name:'',//姓名
age:'',//年龄 age:'',//年龄
gender:'male',//性别|male-男性, female-女性, other-其他 gender:'male',//性别|male-男性, female-女性, other-其他
phone_number:'',//联系电话 phone_number:'',//联系电话
demand:'',//需求 demand:'',//需求
purchasing_power:'',//购买力
cognitive_idea:'',//认知理念
optional_class_time:'',//可选上课时间
distance:'',//距离
decision_maker:'',//决策人 decision_maker:'',//决策人
initial_intent:'',//客户初步意向度: high-高, medium-中, low-低 initial_intent:'',//客户初步意向度: high-高, medium-中, low-低
campus:'',//所属校区
status:'',//客户状态: active-活跃, inactive-不活跃, pending-待定 status:'',//客户状态: active-活跃, inactive-不活跃, pending-待定
//六要素信息 //六要素信息
purchasing_power:'',//购买力
cognitive_idea:'',//认知理念
communication:'',//沟通备注
promised_visit_time:'',//承诺到访时间
staff_id:'',//人员ID
distance:'',//距离
optional_class_time:'',//可选上课时间
}, },
//下拉选择器相关 //下拉选择器相关
@ -580,14 +626,10 @@ export default {
source_channel:{ source_channel:{
text:'',//回显中文名字 text:'',//回显中文名字
options:[ options:[
{ // {
text:'张三', // text:'张三',
value:'1' // value:'1'
}, // }
{
text:'fg方法',
value:'2'
},
],//可选值列表 ],//可选值列表
}, },
//来源 //来源
@ -660,30 +702,26 @@ export default {
} }
}, },
onShow() { onShow() {
// this.init() this.init()
}, },
methods: { methods: {
//初始化 //初始化
async init() { async init() {
//获取登录用户信息 //获取登录用户信息
this.getUserInfo() this.getUserInfo()
this.getDict_courses_id()//获取字典-课程id选择 await this.getDict('source_channel')//获取字典-来源渠道
this.getDict_source_channel()//获取字典-来源渠道 await this.getDict('source')//获取字典-来源
this.getDict_customer_source()//获取字典-客户来源 await this.getDict('purchasing_power')//获取字典-购买力
this.getDict_customer_tags()//获取字典-客户标签 await this.getDict('initial_intent')//获取字典-客户初步意向度
await this.getDict('cognitive_idea')//获取字典-认知理念
this.getStaffList()//获取人员列表 await this.getDict('status')//获取字典-客户状态
// this.getStaffList()//获取人员列表
this.getRoleStaffList(5)//获取市场人员列表 // this.getAreaTree()//获取地区树形结构
this.getRoleStaffList(6)//获取销售人员列表
this.getAreaTree()//获取地区树形结构
}, },
//获取用户信息
async getUserInfo(){ async getUserInfo(){
let res = await marketApi.member({}) let res = await apiRoute.getPersonnelInfo({})
if (res.code != 1) { if (res.code != 1) {
uni.showToast({ uni.showToast({
title: res.msg, title: res.msg,
@ -693,10 +731,10 @@ export default {
} }
this.userInfo = res.data this.userInfo = res.data
console.log(111,res.data)
this.formData.add_staff_id = res.data.staff_id//顾问id this.formData.consultant = res.data.id//顾问id
this.str_add_staff_id = res.data.name//顾问名字 this.formData.staff_id = res.data.id//人员ID
this.picker_config['consultant'].text = res.data.name//顾问名字
}, },
//获取字典-课程id选择 //获取字典-课程id选择
@ -787,32 +825,41 @@ export default {
this.options_area = res.data this.options_area = res.data
}, },
//获取字典-来源渠道 //获取字典
async getDict_source_channel(){ async getDict(inputName){
let res = await commonApi.getDictionary('source_channel') let key = ''
if(res.code != 1){ switch (inputName){
uni.showToast({ //来源渠道
title: res.msg, case 'source_channel':
icon: 'none' key = 'SourceChannel'
}) break;
//来源
case 'source':
key = 'source'
break;
//购买力
case 'purchasing_power':
key = 'customer_purchasing_power'
break;
//认知理念
case 'cognitive_idea':
key = 'cognitive_concept'
break;
//客户初步意向度
case 'initial_intent':
key = 'preliminarycustomerintention'
break;
//客户状态
case 'status':
key = 'kh_status'
break;
}
if(!key){
return return
} }
let dictionary = res.data.dictionary
let arr = []
dictionary.forEach((v,k)=>{
arr.push({
text: v.name,
value: v.value,
})
})
this.options_source_channel = arr
},
let res = await apiRoute.common_Dictionary({key:key})
//获取字典-客户来源
async getDict_customer_source(){
let res = await commonApi.getDictionary('customer_source')
if(res.code != 1){ if(res.code != 1){
uni.showToast({ uni.showToast({
title: res.msg, title: res.msg,
@ -829,30 +876,20 @@ export default {
value: v.value, value: v.value,
}) })
}) })
this.options_customer_source = arr
},
//获取字典-客户标签 if(inputName == 'source_channel'){
async getDict_customer_tags(){ //插入到arr的头部
let res = await commonApi.getDictionary('customer_tags') arr.unshift({
if(res.code != 1){ text: '线下',
uni.showToast({ value: '0',
title: res.msg, })
icon: 'none' }
}) if(inputName == 'status'){
return //插入到arr的头部
console.log(arr)
} }
let dictionary = res.data.dictionary this.picker_config[inputName].options = arr
let arr = []
dictionary.forEach((v,k)=>{
arr.push({
text: v.name,
value: String(v.value),
checked: false,
})
})
this.options_customer_tags = arr
}, },
//##### 查重相关 ##### //##### 查重相关 #####
@ -941,126 +978,7 @@ export default {
//表单验证
async validatorForm(data) {
//课程id
if(!data.courses_id){
uni.showToast({
title: '请选择课程',
icon: 'none'
})
return false
}
//线索标题
if(!data.title){
uni.showToast({
title: '线索标题必填',
icon: 'none'
})
return false
}
//学生姓名
if(!data.student_name){
uni.showToast({
title: '学生姓名必填',
icon: 'none'
})
return false
}
//年龄
if(!data.age){
uni.showToast({
title: '年龄必填',
icon: 'none'
})
return false
}
//性别
if(!data.sex){
uni.showToast({
title: '性别必填',
icon: 'none'
})
return false
}
//电话
if(!data.student_phone){
uni.showToast({
title: '电话必填',
icon: 'none'
})
return false
}
//##### 跟进 #####
if(data.is_follow == 1){
//跟进类型
if(!data.entry_type){
uni.showToast({
title: '跟进类型必填',
icon: 'none'
})
return false
}
//跟进人员
if(!data.staff_id){
uni.showToast({
title: '跟进人员必填',
icon: 'none'
})
return false
}
//跟进时间
if(!data.follow_up_time){
uni.showToast({
title: '跟进时间必填',
icon: 'none'
})
return false
}
}
return true
},
//提交
async submit() {
console.log('提交',this.formData)
let data = {...this.formData}
//表单验证
let validatorForm = await this.validatorForm(data)
console.log('验证结果',validatorForm)
if(!validatorForm){
return
}
//防止重复提交
if (!this.is_submit) {
return
}
this.is_submit = false
let res = await marketApi.setSales(data)
this.is_submit = true
if(res.code != 1){
uni.showToast({
title: res.msg,
icon: 'none'
})
return
}
uni.showToast({
title: res.msg,
icon: 'success'
})
//延迟1s执行
setTimeout(() => {
//跳转页面-线索列表
uni.navigateTo({
url: `/pages/market/clue/index`
})
}, 1000)
},
@ -1140,15 +1058,23 @@ export default {
//######-----下拉选择器组件相关-----###### //######-----下拉选择器组件相关-----######
//打开下拉选择器 //打开下拉选择器
openCicker(input_name, linkage = true) { openCicker(input_name, linkage = true) {
this.picker_show = true this.picker_options = []
this.picker_input_name = input_name this.picker_input_name = input_name
console.log('xxx',this.picker_config[input_name]?.options || 6666) let arr = this.picker_config[input_name]?.options || []
this.picker_options = this.picker_config[input_name]['options'] if (!arr.length) {
uni.showToast({ title: '暂无选项', icon: 'none' })
return
}
this.picker_options =arr
this.picker_linkage = linkage this.picker_linkage = linkage
// 使用 nextTick 确保数据更新后再打开 picker
this.$nextTick(() => {
this.picker_show = true
})
}, },
//监听-下拉选择器 //监听-下拉选择器
changeCicker(e) { changeCicker(e) {
@ -1189,6 +1115,205 @@ export default {
cancel_date() { cancel_date() {
this.date_picker_show = false this.date_picker_show = false
}, },
//下一步 index|0=添加客户,1六要素
async nextStep(index) {
this.optionTableId = String(index)
},
//表单验证
async validatorForm(data) {
//客户基础信息
//来源渠道
if(!data.source_channel.length){
uni.showToast({
title: '请选择来源渠道',
icon: 'none'
})
this.nextStep('0')
return false
}
//来源
if(!data.source){
uni.showToast({
title: '请选择来源',
icon: 'none'
})
this.nextStep('0')
return false
}
//姓名
if(!data.name){
uni.showToast({
title: '学生姓名必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//年龄
if(!data.age){
uni.showToast({
title: '年龄必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//性别
if(!data.gender){
uni.showToast({
title: '性别必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//电话
if(!data.phone_number){
uni.showToast({
title: '电话必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//需求
if(!data.demand){
uni.showToast({
title: '需求必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//决策人
if(!data.decision_maker){
uni.showToast({
title: '决策人必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//客户初步意向度必填
if(!data.initial_intent){
uni.showToast({
title: '客户初步意向度必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//客户状态
if(!data.status){
uni.showToast({
title: '客户状态必填',
icon: 'none'
})
this.nextStep('0')
return false
}
//##### 六要素信息 #####
//购买力
if(!data.purchasing_power){
uni.showToast({
title: '购买力必填',
icon: 'none'
})
this.nextStep('1')
return false
}
//认知理念
if(!data.cognitive_idea){
uni.showToast({
title: '认知理念必填',
icon: 'none'
})
this.nextStep('1')
return false
}
//沟通备注
if(!data.communication){
uni.showToast({
title: '沟通备注必填',
icon: 'none'
})
this.nextStep('1')
return false
}
//承诺到访时间
if(!data.promised_visit_time){
uni.showToast({
title: '承诺到访时间必填',
icon: 'none'
})
this.nextStep('1')
return false
}
//距离
if(!data.distance){
uni.showToast({
title: '距离必填',
icon: 'none'
})
this.nextStep('1')
return false
}
//可选上课时间
if(!data.optional_class_time){
uni.showToast({
title: '可选上课时间必填',
icon: 'none'
})
this.nextStep('1')
return false
}
return true
},
//提交
async submit() {
console.log('提交',this.formData)
let data = {...this.formData}
//表单验证
let validatorForm = await this.validatorForm(data)
console.log('验证结果',validatorForm)
if(!validatorForm){
return
}
//防止重复提交
if (!this.is_submit) {
return
}
this.is_submit = false
let res = await apiRoute.xs_addCustomerResources(data)
this.is_submit = true
if(res.code != 1){
uni.showToast({
title: res.msg,
icon: 'none'
})
return
}
uni.showToast({
title: res.msg,
icon: 'success'
})
//延迟1s执行
setTimeout(() => {
//跳转页面-线索列表
uni.navigateTo({
url: `/pages/market/clue/index`
})
}, 1000)
},
} }
} }
</script> </script>

2
pages/market/clue/index.vue

@ -182,7 +182,7 @@ export default {
}, },
onLoad(options) {}, onLoad(options) {},
onShow(){ onShow(){
this.init()//初始化 // this.init()//初始化
}, },
//下拉刷新 //下拉刷新
async onPullDownRefresh() { async onPullDownRefresh() {

Loading…
Cancel
Save