Browse Source

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

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

683
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,6 +212,81 @@
></fui-input> ></fui-input>
</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]"
placeholder="点击填写"
v-model="formData.decision_maker"
backgroundColor="#434544"
size="26"
color="#fff"
></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(`initial_intent`)">
{{ (formData.initial_intent) ? picker_config.initial_intent.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(`status`)">
{{ (formData.status) ? picker_config.status.text : '点击选择' }}
</view>
</view>
</fui-form-item>
</view>
</fui-form>
</view>
<view class="fui-btn__box">
<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 <fui-form-item
label="购买力" label="购买力"
@ -246,6 +344,25 @@
</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="openDate(`promised_visit_time`)">
{{ (formData.promised_visit_time) ? formData.promised_visit_time : '点击选择' }}
</view>
</view>
</fui-form-item>
<!--距离--> <!--距离-->
<fui-form-item <fui-form-item
label="距离" label="距离"
@ -267,9 +384,9 @@
></fui-input> ></fui-input>
</view> </view>
</fui-form-item> </fui-form-item>
<!--决策人--> <!--沟通备注-->
<fui-form-item <fui-form-item
label="决策人" label="沟通备注"
asterisk asteriskPosition="right" asterisk asteriskPosition="right"
labelSize='26' labelSize='26'
prop="title" prop="title"
@ -281,82 +398,19 @@
:borderBottom="false" :borderBottom="false"
:padding="[0]" :padding="[0]"
placeholder="点击填写" placeholder="点击填写"
v-model="formData.decision_maker" v-model="formData.communication"
backgroundColor="#434544" backgroundColor="#434544"
size="26" size="26"
color="#fff" color="#fff"
></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(`initial_intent`)">
{{ (formData.initial_intent) ? picker_config.initial_intent.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(`campus`)">
{{ (formData.campus) ? picker_config.campus.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(`status`)">
{{ (formData.status) ? picker_config.status.text : '点击选择' }}
</view>
</view>
</fui-form-item>
</view> </view>
</fui-form> </fui-form>
</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="submit">保存</fui-button>
</view>
</view> </view>
<!-- 添加六要素-->
<view style="margin-top: 20rpx;" v-if="optionTableId == 1">
六要素
</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'
}) })
return }
if(inputName == 'status'){
//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