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;
})
},
//获取字典数据
common_Dictionary(data = {}) {
let url = '/common/getDictionary'
return http.get(url, data).then(res => {
return res;
})
},
@ -118,12 +125,20 @@ export default {
//↓↓↓↓↓↓↓↓↓↓↓↓-----销售接口相关-----↓↓↓↓↓↓↓↓↓↓↓↓
//修改销售端个人资料
editPersonnel(data = {}) {
let url = '/personnel/info'
return http.get(url, data).then(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 class="search_box">
<view class="input_box">
<input type="text" v-model="student_name" placeholder="请输入客户名称">
</view>
<view class="btn" @click="clientList()">查重</view>
</view>
<!-- <view class="search_box">-->
<!-- <view class="input_box">-->
<!-- <input type="text" v-model="student_name" placeholder="请输入客户名称">-->
<!-- </view>-->
<!-- <view class="btn" @click="clientList()">查重</view>-->
<!-- </view>-->
<view class="form-style">
<fui-form ref="form" top="0" :model="formData" :show="false">
@ -66,6 +66,7 @@
</view>
</fui-form-item>
<!--顾问-->
<!--
<fui-form-item
label="顾问"
asterisk asteriskPosition="right"
@ -84,6 +85,28 @@
</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]"
:disabled="true"
placeholder="点击填写"
v-model="picker_config.consultant.text"
backgroundColor="#434544"
size="26"
color="#808080"
></fui-input>
</view>
</fui-form-item>
<!--姓名-->
<fui-form-item
label="姓名"
@ -189,84 +212,6 @@
></fui-input>
</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(`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
label="决策人"
@ -307,25 +252,6 @@
</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(`campus`)">
{{ (formData.campus) ? picker_config.campus.text : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--客户状态-->
<fui-form-item
label="客户状态"
@ -350,13 +276,141 @@
</view>
<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 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>
@ -451,6 +505,7 @@
</template>
<script>
import apiRoute from '@/api/apiRoute.js';
import commonApi from '@/api/common.js';
import marketApi from '@/api/market.js';
import memberApi from '@/api/member.js';
@ -535,34 +590,25 @@ export default {
formData: {
// 客户基础信息
source_channel:'',//来源渠道
source:'',//来源
consultant:'',//顾问
name:'',//姓名
age:'',//年龄
gender:'male',//性别|male-男性, female-女性, other-其他
phone_number:'',//联系电话
demand:'',//需求
purchasing_power:'',//购买力
cognitive_idea:'',//认知理念
optional_class_time:'',//可选上课时间
distance:'',//距离
decision_maker:'',//决策人
initial_intent:'',//客户初步意向度: high-高, medium-中, low-低
campus:'',//所属校区
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:{
text:'',//回显中文名字
options:[
{
text:'张三',
value:'1'
},
{
text:'fg方法',
value:'2'
},
// {
// text:'张三',
// value:'1'
// }
],//可选值列表
},
//来源
@ -660,30 +702,26 @@ export default {
}
},
onShow() {
// this.init()
this.init()
},
methods: {
//初始化
async init() {
//获取登录用户信息
this.getUserInfo()
this.getDict_courses_id()//获取字典-课程id选择
this.getDict_source_channel()//获取字典-来源渠道
this.getDict_customer_source()//获取字典-客户来源
this.getDict_customer_tags()//获取字典-客户标签
this.getStaffList()//获取人员列表
this.getRoleStaffList(5)//获取市场人员列表
this.getRoleStaffList(6)//获取销售人员列表
this.getAreaTree()//获取地区树形结构
await this.getDict('source_channel')//获取字典-来源渠道
await this.getDict('source')//获取字典-来源
await this.getDict('purchasing_power')//获取字典-购买力
await this.getDict('initial_intent')//获取字典-客户初步意向度
await this.getDict('cognitive_idea')//获取字典-认知理念
await this.getDict('status')//获取字典-客户状态
// this.getStaffList()//获取人员列表
// this.getAreaTree()//获取地区树形结构
},
//获取用户信息
async getUserInfo(){
let res = await marketApi.member({})
let res = await apiRoute.getPersonnelInfo({})
if (res.code != 1) {
uni.showToast({
title: res.msg,
@ -693,10 +731,10 @@ export default {
}
this.userInfo = res.data
console.log(111,res.data)
this.formData.add_staff_id = res.data.staff_id//顾问id
this.str_add_staff_id = res.data.name//顾问名字
this.formData.consultant = res.data.id//顾问id
this.formData.staff_id = res.data.id//人员ID
this.picker_config['consultant'].text = res.data.name//顾问名字
},
//获取字典-课程id选择
@ -787,32 +825,41 @@ export default {
this.options_area = res.data
},
//获取字典-来源渠道
async getDict_source_channel(){
let res = await commonApi.getDictionary('source_channel')
if(res.code != 1){
uni.showToast({
title: res.msg,
icon: 'none'
})
//获取字典
async getDict(inputName){
let key = ''
switch (inputName){
//来源渠道
case 'source_channel':
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
}
let dictionary = res.data.dictionary
let arr = []
dictionary.forEach((v,k)=>{
arr.push({
text: v.name,
value: v.value,
})
})
this.options_source_channel = arr
},
//获取字典-客户来源
async getDict_customer_source(){
let res = await commonApi.getDictionary('customer_source')
let res = await apiRoute.common_Dictionary({key:key})
if(res.code != 1){
uni.showToast({
title: res.msg,
@ -829,30 +876,20 @@ export default {
value: v.value,
})
})
this.options_customer_source = arr
},
//获取字典-客户标签
async getDict_customer_tags(){
let res = await commonApi.getDictionary('customer_tags')
if(res.code != 1){
uni.showToast({
title: res.msg,
icon: 'none'
})
return
if(inputName == 'source_channel'){
//插入到arr的头部
arr.unshift({
text: '线下',
value: '0',
})
}
if(inputName == 'status'){
//插入到arr的头部
console.log(arr)
}
let dictionary = res.data.dictionary
let arr = []
dictionary.forEach((v,k)=>{
arr.push({
text: v.name,
value: String(v.value),
checked: false,
})
})
this.options_customer_tags = arr
this.picker_config[inputName].options = 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) {
this.picker_show = true
this.picker_options = []
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
// 使用 nextTick 确保数据更新后再打开 picker
this.$nextTick(() => {
this.picker_show = true
})
},
//监听-下拉选择器
changeCicker(e) {
@ -1189,6 +1115,205 @@ export default {
cancel_date() {
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>

2
pages/market/clue/index.vue

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

Loading…
Cancel
Save