You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2268 lines
64 KiB
2268 lines
64 KiB
<!--添加客户-->
|
|
<template>
|
|
<view class="assemble">
|
|
<fui-segmented-control
|
|
style="padding-top: 30rpx;"
|
|
:values="optionTable"
|
|
:current="(Number(optionTableId))"
|
|
type="text"
|
|
activeColor="#29d3b4"
|
|
color="#fff"
|
|
@click="segmented">
|
|
</fui-segmented-control>
|
|
|
|
|
|
<!-- 添加客户-->
|
|
<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="form-style">
|
|
<fui-form ref="form" top="0" :model="formData" :show="false">
|
|
|
|
<view class="title"
|
|
style="margin-top: 20rpx; display: flex; justify-content: space-between; align-items: center;">
|
|
<text>基础信息</text>
|
|
<view class="quick-fill-btn" @click="openQuickFill">
|
|
<text style="color: #29d3b4; font-size: 24rpx;">快速填写</text>
|
|
</view>
|
|
</view>
|
|
<view class="input-style">
|
|
<!--姓名-->
|
|
<fui-form-item
|
|
label="姓名"
|
|
labelSize='26'
|
|
asterisk asteriskPosition="right"
|
|
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.name"
|
|
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.phone_number"
|
|
backgroundColor="#434544"
|
|
size="26"
|
|
color="#fff"
|
|
@blur="handlePhoneBlur"
|
|
></fui-input>
|
|
</view>
|
|
</fui-form-item>
|
|
|
|
<!--校区-->
|
|
<fui-form-item
|
|
label="校区"
|
|
labelSize='26'
|
|
prop="campus"
|
|
asterisk asteriskPosition="right"
|
|
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="来源"
|
|
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(`source`)">
|
|
{{ (formData.source) ? picker_config.source.text : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
|
|
<!--来源渠道-->
|
|
<fui-form-item
|
|
v-if="formData.source == 1"
|
|
label="来源渠道"
|
|
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(`source_channel`)">
|
|
{{ (formData.source_channel) ? picker_config.source_channel.text : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
|
|
<!--转介绍资源选择-->
|
|
<fui-form-item
|
|
v-if="formData.source == 3"
|
|
label="转介绍资源"
|
|
asterisk asteriskPosition="right"
|
|
labelSize='26'
|
|
prop=""
|
|
background='#434544'
|
|
labelColor='#fff'
|
|
:bottomBorder='false'
|
|
>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<!-- 搜索输入框 -->
|
|
<view class="referral-search-container">
|
|
<fui-input
|
|
:borderBottom="false"
|
|
:padding="[0]"
|
|
placeholder="输入姓名或手机号搜索"
|
|
v-model="referralSearchQuery"
|
|
backgroundColor="#434544"
|
|
size="26"
|
|
color="#fff"
|
|
@input="searchReferralResources"
|
|
></fui-input>
|
|
|
|
<!-- 搜索结果列表 -->
|
|
<view v-if="referralSearchResults.length > 0" class="referral-search-results">
|
|
<view
|
|
v-for="resource in referralSearchResults"
|
|
:key="resource.id"
|
|
class="referral-search-item"
|
|
:class="{ 'selected': formData.referral_resource_id === resource.id }"
|
|
@click="selectReferralResource(resource)"
|
|
>
|
|
<view class="resource-info">
|
|
<view class="resource-name">{{ resource.name }}</view>
|
|
<view class="resource-phone">{{ resource.phone_number }}</view>
|
|
</view>
|
|
<view v-if="formData.referral_resource_id === resource.id" class="check-icon">✓</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 已选择的资源显示 -->
|
|
<view v-if="selectedReferralResource && !referralSearchQuery" class="selected-referral-resource">
|
|
<view class="selected-resource-info">
|
|
<view class="selected-resource-name">{{ selectedReferralResource.name }}</view>
|
|
<view class="selected-resource-phone">{{ selectedReferralResource.phone_number }}</view>
|
|
</view>
|
|
<view class="clear-selection" @click="clearReferralSelection">✕</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
|
|
<fui-form-item
|
|
v-show="false"
|
|
label="顾问"
|
|
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="年龄"
|
|
labelSize='26'
|
|
prop="age"
|
|
background='#434544'
|
|
labelColor='#fff'
|
|
:bottomBorder='false'>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<fui-input
|
|
:borderBottom="false"
|
|
:padding="[0]"
|
|
placeholder="请输入年龄(如5.3)"
|
|
v-model="formData.age"
|
|
backgroundColor="#434544"
|
|
size="26"
|
|
color="#fff"
|
|
type="digit"
|
|
@blur="handleAgeBlur"
|
|
></fui-input>
|
|
</view>
|
|
</fui-form-item>
|
|
<!--客户初步意向度-->
|
|
<fui-form-item
|
|
label="客户初步意向度"
|
|
labelWidth="240"
|
|
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
|
|
v-show="false"
|
|
label="客户状态"
|
|
|
|
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
|
|
label="一、需求"
|
|
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.demand"
|
|
backgroundColor="#434544"
|
|
size="26"
|
|
color="#fff"
|
|
></fui-input>
|
|
</view>
|
|
</fui-form-item>
|
|
<!--购买力-->
|
|
<fui-form-item
|
|
label="二、购买力"
|
|
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="三、认知理念"
|
|
label-width="210"
|
|
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>
|
|
<view style="color: #ffffff;width: 100%;text-align: left;margin: 10px;">
|
|
四、时间/距离
|
|
</view>
|
|
|
|
<!--可选上课时间-->
|
|
<fui-form-item
|
|
label="1、可选上课时间"
|
|
labelWidth="240"
|
|
labelSize='26'
|
|
prop=""
|
|
background='#434544'
|
|
labelColor='#fff'
|
|
:bottomBorder='false'
|
|
>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<fui-input
|
|
:borderBottom="false"
|
|
:padding="[0]"
|
|
placeholder="填写可选上课时间"
|
|
v-model="formData.optional_class_time"
|
|
backgroundColor="#434544"
|
|
size="26"
|
|
color="#fff"
|
|
></fui-input>
|
|
<!-- <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="2、承诺到访时间"
|
|
labelSize='26'
|
|
labelWidth="240"
|
|
prop=""
|
|
background='#434544'
|
|
labelColor='#fff'
|
|
:bottomBorder='false'
|
|
>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<view
|
|
class="input-title"
|
|
style="margin-right:14rpx;"
|
|
@click="openDateTime(`promised_visit_time`)">
|
|
{{ (formData.promised_visit_time) ? formData.promised_visit_time : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
<!--距离-->
|
|
<fui-form-item
|
|
label="3、距离"
|
|
labelSize='26'
|
|
label-width="210"
|
|
prop="title"
|
|
background='#434544'
|
|
labelColor='#fff'
|
|
:bottomBorder='false'>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<view
|
|
class="input-title"
|
|
style="margin-right:14rpx;"
|
|
@click="openCicker(`distance`)">
|
|
{{ (formData.distance) ? picker_config.distance.text : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
<!-- 决策人 -->
|
|
<fui-form-item label="五、决策人" labelSize='26' prop="decision_maker" background='#434544' labelColor='#fff'
|
|
:bottomBorder='false'>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<view class="input-title" style="margin-right:14rpx;" @click="openCicker('decision_maker')">
|
|
{{ formData.decision_maker ? picker_config.decision_maker.text : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
<!-- 情感粘度 -->
|
|
<fui-form-item
|
|
label="六、情感粘度"
|
|
labelSize='26'
|
|
label-width="210"
|
|
prop="emotional_stickiness_score" background='#434544' labelColor='#fff'
|
|
:bottomBorder='false'>
|
|
<view class="input-title" style="margin-right:14rpx;">
|
|
<view class="input-title" style="margin-right:14rpx;" @click="openCicker('emotional_stickiness_score')">
|
|
{{ formData.emotional_stickiness_score ? picker_config.emotional_stickiness_score.text : '点击选择' }}
|
|
</view>
|
|
</view>
|
|
</fui-form-item>
|
|
<!--沟通备注-->
|
|
<fui-form-item
|
|
label="沟通备注"
|
|
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>
|
|
|
|
|
|
<!-- 年月日-选择时间 -->
|
|
<fui-date-picker
|
|
:show="date_picker_show"
|
|
type="5"
|
|
:startYear="2020"
|
|
:endYear="2030"
|
|
:value="getCurrentDate()"
|
|
@change="change_date"
|
|
@cancel="cancel_date">
|
|
</fui-date-picker>
|
|
|
|
<!-- 日期时间选择器 -->
|
|
<fui-date-picker
|
|
:show="datetime_picker_show"
|
|
type="1"
|
|
:startYear="2020"
|
|
:endYear="2030"
|
|
:value="getCurrentDateTime()"
|
|
@change="change_datetime"
|
|
@cancel="cancel_datetime">
|
|
</fui-date-picker>
|
|
|
|
<!-- 选择器 -->
|
|
<fui-picker
|
|
:linkage='picker_linkage'
|
|
:options="picker_options"
|
|
:layer="1"
|
|
:show="picker_show"
|
|
@change="changeCicker"
|
|
@cancel="cancelCicker">
|
|
</fui-picker>
|
|
|
|
<!-- 查重弹出层-->
|
|
<fui-bottom-popup :show="showDuplicateCheck" @close="closeDuplicateCheck">
|
|
<view class="fui-scroll__wrap">
|
|
<view class="title_box">
|
|
<view></view>
|
|
<view class="title">查重结果</view>
|
|
<view class="close" @tap="closeDuplicateCheck">
|
|
<fui-icon name="close" :size="48"></fui-icon>
|
|
</view>
|
|
</view>
|
|
|
|
<scroll-view scroll-y class="section_ul">
|
|
<!--暂无数据时展示-->
|
|
<view class="not_list" v-if="clientUserList.length == 0">
|
|
<image :src="$util.img('/uniapp_src/static/images/index/zan_wu.png')" class="img"></image>
|
|
<view class="title">暂无重复客户</view>
|
|
</view>
|
|
|
|
<!--数据列表-->
|
|
<view class="ul" v-else>
|
|
<view class="duplicate-notice">
|
|
<text style="color: #ff6b35; font-size: 28rpx; margin-bottom: 20rpx;">
|
|
检测到手机号重复,是否为现有用户添加新学员?
|
|
</text>
|
|
<fui-button
|
|
background="#29d3b4"
|
|
color="#fff"
|
|
@click="confirmAddStudent"
|
|
style="margin: 20rpx 0;">
|
|
确认添加学员
|
|
</fui-button>
|
|
</view>
|
|
<view class="li" v-for="(v,k) in clientUserList" :key="k" @click="openViewClueInfo(v)">
|
|
<view class="left_box">
|
|
<view class="box_1">
|
|
<image
|
|
class="img"
|
|
:src="$util.img('/uniapp_src/static/images/index/myk.png')"></image>
|
|
<view class="name">{{ v.name }}</view>
|
|
</view>
|
|
<view class="box_2">
|
|
<view class="left">
|
|
<view class="name">首选联系人:{{ v.decision_maker }}</view>
|
|
</view>
|
|
</view>
|
|
<view class="box_2">
|
|
<view class="left">
|
|
<view class="name">联系电话:{{ v.phone_number || '' }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="box_3">
|
|
<view class="left">
|
|
{{ $util.formatToDateTime((v.updated_at || ''), 'm-d H:i') }} 跟进
|
|
</view>
|
|
<view class="right">
|
|
|
|
<image
|
|
v-if="v.initial_intent == 'high'"
|
|
:src="$util.img('/uniapp_src/static/images/index/intention3.png')"
|
|
class="img"
|
|
></image>
|
|
<image
|
|
v-else-if="v.initial_intent == 'medium'"
|
|
:src="$util.img('/uniapp_src/static/images/index/intention2.png')"
|
|
class="img"
|
|
></image>
|
|
<image
|
|
v-else
|
|
:src="$util.img('/uniapp_src/static/images/index/intention1.png')"
|
|
class="img"
|
|
></image>
|
|
|
|
<view>意向:{{ v.initial_intent_name || '' }}</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="right_box">
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</scroll-view>
|
|
|
|
</view>
|
|
</fui-bottom-popup>
|
|
|
|
<!-- 快速填写弹窗 -->
|
|
<view v-if="showQuickFill" class="quick-fill-mask" @tap="showQuickFill=false">
|
|
<view class="quick-fill-content" @tap.stop>
|
|
<view class="quick-fill-header">
|
|
<view class="quick-fill-title">快速填写</view>
|
|
<view class="quick-fill-close" @tap="showQuickFill=false">
|
|
<text class="close-text">✕</text>
|
|
</view>
|
|
</view>
|
|
<view class="quick-fill-body">
|
|
<view class="quick-fill-tip">
|
|
<text>请粘贴包含客户信息的文本,支持格式:</text>
|
|
<text>姓名:张三,电话:13800138000,校区:测试校区</text>
|
|
</view>
|
|
<textarea
|
|
class="quick-fill-textarea"
|
|
placeholder="请粘贴客户信息文本..."
|
|
v-model="quickFillText"
|
|
:maxlength="1000"
|
|
></textarea>
|
|
</view>
|
|
<view class="quick-fill-buttons">
|
|
<view class="quick-fill-btn cancel-btn" @click="showQuickFill=false">取消</view>
|
|
<view class="quick-fill-btn confirm-btn" @click="parseQuickFillText">解析并填写</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import apiRoute from '@/api/apiRoute.js'
|
|
import util from '@/common/util.js'
|
|
import dictUtilSimple from '@/common/dictUtilSimple.js'
|
|
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
switchChange_type: 1,
|
|
|
|
is_submit: true,//是否提交(防止重复提交)|true=可提交,false=不可提交
|
|
|
|
// 快速填写相关
|
|
showQuickFill: false, // 是否显示快速填写弹窗
|
|
quickFillText: '', // 快速填写文本内容
|
|
|
|
//表单
|
|
formData: {
|
|
// 客户基础信息
|
|
source_channel: '',//来源渠道
|
|
source: '',//来源
|
|
consultant: '',//顾问
|
|
name: '',//姓名
|
|
age: '',//年龄(小数)
|
|
gender: 'male',//性别|male-男性, female-女性, other-其他
|
|
phone_number: '',//联系电话
|
|
demand: '',//需求
|
|
decision_maker: '',//决策人
|
|
initial_intent: '',//客户初步意向度: high-高, medium-中, low-低
|
|
status: 'pending',//客户状态: active-活跃, inactive-不活跃, pending-待定
|
|
birthday: '',//生日(根据年龄自动计算)
|
|
|
|
//六要素信息
|
|
purchasing_power: '',//购买力
|
|
cognitive_idea: '',//认知理念
|
|
communication: '',//沟通备注
|
|
promised_visit_time: '',//承诺到访时间
|
|
staff_id: '',//人员ID
|
|
distance: '',//距离
|
|
optional_class_time: '',//可选上课时间
|
|
campus: '',
|
|
referral_resource_id: '',//转介绍资源ID
|
|
emotional_stickiness_score: '',//情感粘性
|
|
},
|
|
campus_list: [],
|
|
//下拉选择器相关
|
|
picker_input_name: '',//下拉组件的input_name
|
|
picker_show: false,//下拉组件是否展示
|
|
picker_linkage: true,//选择器是否为联动选择
|
|
picker_options: [
|
|
// {
|
|
// text:'张三',
|
|
// value:'1'
|
|
// },
|
|
],//选择器可选值列表
|
|
picker_config: {
|
|
//来源渠道
|
|
source_channel: {
|
|
text: '',//回显中文名字
|
|
options: [
|
|
// {
|
|
// text:'张三',
|
|
// value:'1'
|
|
// }
|
|
],//可选值列表
|
|
},
|
|
//来源
|
|
source: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//顾问
|
|
consultant: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//购买力
|
|
purchasing_power: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//认知理念
|
|
cognitive_idea: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//客户初步意向度
|
|
initial_intent: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//决策人
|
|
decision_maker: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//所属校区
|
|
campus: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//客户状态
|
|
status: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
//距离
|
|
distance: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
emotional_stickiness_score: {
|
|
text: '',
|
|
options: [],
|
|
},
|
|
},//选择器选项配置
|
|
|
|
// 年月日选择组件
|
|
data_picker_input_name: '',//时间组件的input_name
|
|
date_picker_show: false,//时间选择器是否展示
|
|
|
|
// 日期时间选择组件
|
|
datetime_picker_input_name: '',//日期时间组件的input_name
|
|
datetime_picker_show: false,//日期时间选择器是否展示
|
|
|
|
|
|
//登录用户信息
|
|
userInfo: {},
|
|
|
|
// 查重相关
|
|
student_name: '',//检索关键字
|
|
clientUserList: [],//查重用户列表
|
|
showDuplicateCheck: false,//是否显示查重弹出层
|
|
|
|
|
|
//tab切换
|
|
optionTableId: 0,
|
|
optionTable: [
|
|
{
|
|
id: 0,
|
|
name: '添加客户',
|
|
},
|
|
{
|
|
id: 1,
|
|
name: '添加六要素',
|
|
},
|
|
],
|
|
|
|
// 转介绍资源相关
|
|
referralSearchQuery: '', // 转介绍资源搜索关键词
|
|
referralSearchResults: [], // 搜索结果列表
|
|
selectedReferralResource: null, // 已选择的转介绍资源
|
|
referralSearchTimer: null, // 搜索防抖定时器
|
|
}
|
|
},
|
|
onLoad() {
|
|
// 预加载字典数据
|
|
this.preloadDictData()
|
|
},
|
|
onShow() {
|
|
this.init()
|
|
},
|
|
methods: {
|
|
// 预加载字典数据
|
|
async preloadDictData() {
|
|
const dictKeys = [
|
|
'SourceChannel', 'source', 'customer_purchasing_power',
|
|
'preliminarycustomerintention', 'cognitive_concept',
|
|
'kh_status', 'decision_maker', 'distance','emotional_stickiness_score'
|
|
]
|
|
|
|
// 静默预加载,不阻塞页面显示
|
|
// 暂时使用简化版本进行测试
|
|
dictUtilSimple.getBatchDict(dictKeys).catch(error => {
|
|
console.warn('字典预加载失败:', error)
|
|
})
|
|
},
|
|
|
|
//初始化
|
|
async init() {
|
|
//获取登录用户信息
|
|
await this.getUserInfo()
|
|
|
|
// 使用批量获取字典数据,提升性能
|
|
await this.getBatchDictData()
|
|
|
|
// 设置时间相关默认值
|
|
this.setDefaultTimes()
|
|
|
|
// this.getStaffList()//获取人员列表
|
|
// this.getAreaTree()//获取地区树形结构
|
|
},
|
|
|
|
// 设置时间相关默认值
|
|
setDefaultTimes() {
|
|
// 移除可选上课时间的默认值设置,让用户手动选择
|
|
this.formData.optional_class_time = ''
|
|
|
|
// 移除承诺到访时间的默认值设置,让用户手动选择
|
|
this.formData.promised_visit_time = ''
|
|
|
|
console.log('时间默认值已清空,用户需手动选择')
|
|
},
|
|
|
|
// 快速填写相关方法
|
|
// 打开快速填写弹窗
|
|
openQuickFill() {
|
|
this.showQuickFill = true
|
|
this.quickFillText = ''
|
|
},
|
|
|
|
// 解析快速填写文本
|
|
parseQuickFillText() {
|
|
if (!this.quickFillText.trim()) {
|
|
uni.showToast({
|
|
title: '请输入要解析的文本',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
try {
|
|
// 定义字段映射规则
|
|
const fieldRules = [
|
|
{ key: 'name', patterns: ['姓名', '客户姓名', '用户姓名', '学员姓名', '学生姓名'] },
|
|
{ key: 'phone_number', patterns: ['电话', '手机', '联系电话', '手机号', '电话号码', '联系方式'] },
|
|
{ key: 'campus', patterns: ['校区', '所属校区', '校区名称'] },
|
|
{ key: 'age', patterns: ['年龄'] },
|
|
{ key: 'birthday', patterns: ['生日', '出生日期', '生日日期'] },
|
|
]
|
|
|
|
// 用于存储解析结果
|
|
const parsedData = {}
|
|
const text = this.quickFillText.trim()
|
|
|
|
// 对每个字段规则进行匹配
|
|
fieldRules.forEach(rule => {
|
|
rule.patterns.forEach(pattern => {
|
|
// 匹配模式:字段名 + 冒号/等号 + 数据内容
|
|
const regex = new RegExp(`${pattern}\\s*[::=]\\s*([^,,\\n\\s]+)`, 'g')
|
|
const match = regex.exec(text)
|
|
if (match && match[1]) {
|
|
parsedData[rule.key] = match[1].trim()
|
|
}
|
|
})
|
|
})
|
|
|
|
console.log('解析结果:', parsedData)
|
|
|
|
// 填写到表单中
|
|
let fillCount = 0
|
|
if (parsedData.name) {
|
|
this.formData.name = parsedData.name
|
|
fillCount++
|
|
}
|
|
if (parsedData.phone_number) {
|
|
this.formData.phone_number = parsedData.phone_number
|
|
fillCount++
|
|
}
|
|
if (parsedData.campus) {
|
|
// 需要在校区选项中查找匹配的项
|
|
this.findAndSetCampus(parsedData.campus)
|
|
fillCount++
|
|
}
|
|
if (parsedData.age) {
|
|
const age = parseFloat(parsedData.age)
|
|
if (!isNaN(age) && age >= 0) {
|
|
this.formData.age = age.toString()
|
|
// 自动计算生日
|
|
this.handleAgeBlur()
|
|
fillCount++
|
|
}
|
|
}
|
|
if (parsedData.birthday) {
|
|
this.formData.birthday = parsedData.birthday
|
|
fillCount++
|
|
}
|
|
|
|
if (fillCount > 0) {
|
|
uni.showToast({
|
|
title: `成功填写${fillCount}个字段`,
|
|
icon: 'success',
|
|
})
|
|
this.showQuickFill = false
|
|
} else {
|
|
uni.showToast({
|
|
title: '未能识别到有效信息,请检查格式',
|
|
icon: 'none',
|
|
})
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('解析失败:', error)
|
|
uni.showToast({
|
|
title: '解析失败,请检查格式',
|
|
icon: 'none',
|
|
})
|
|
}
|
|
},
|
|
|
|
// 查找并设置校区
|
|
findAndSetCampus(campusText) {
|
|
const campusOptions = this.picker_config.campus?.options || []
|
|
const matchedCampus = campusOptions.find(option =>
|
|
option.text.includes(campusText) || campusText.includes(option.text),
|
|
)
|
|
|
|
if (matchedCampus) {
|
|
this.formData.campus = matchedCampus.value
|
|
this.picker_config.campus.text = matchedCampus.text
|
|
}
|
|
},
|
|
|
|
// 统一的日期格式化方法
|
|
formatDate(date) {
|
|
const year = date.getFullYear()
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
|
|
// FirstUI 日期选择器通常支持多种格式
|
|
// 根据实际测试结果可以调整以下格式:
|
|
|
|
// 格式选项(如果当前格式不工作,可以尝试其他格式):
|
|
const formats = {
|
|
standard: `${year}-${month}-${day}`, // YYYY-MM-DD
|
|
chinese: `${year}年${month}月${day}日`, // YYYY年MM月DD日
|
|
slash: `${year}/${month}/${day}`, // YYYY/MM/DD
|
|
dot: `${year}.${month}.${day}`, // YYYY.MM.DD
|
|
space: `${year} ${month} ${day}`, // YYYY MM DD
|
|
}
|
|
|
|
// 优先使用标准格式,如果组件显示异常可以在这里切换格式
|
|
return formats.standard
|
|
|
|
// 如果标准格式不工作,可以尝试:
|
|
// return formats.chinese // 中文格式
|
|
// return formats.slash // 斜杠格式
|
|
},
|
|
|
|
// 统一日期格式处理方法
|
|
normalizeDate(dateStr) {
|
|
if (!dateStr) return ''
|
|
|
|
// 如果已经是标准格式 YYYY-MM-DD,直接返回
|
|
if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) {
|
|
return dateStr
|
|
}
|
|
|
|
// 处理 YYYY/MM/DD 格式
|
|
if (/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(dateStr)) {
|
|
const parts = dateStr.split('/')
|
|
const year = parts[0]
|
|
const month = String(parts[1]).padStart(2, '0')
|
|
const day = String(parts[2]).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
// 处理 YYYY.MM.DD 格式
|
|
if (/^\d{4}\.\d{1,2}\.\d{1,2}$/.test(dateStr)) {
|
|
const parts = dateStr.split('.')
|
|
const year = parts[0]
|
|
const month = String(parts[1]).padStart(2, '0')
|
|
const day = String(parts[2]).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
// 处理中文格式 YYYY年MM月DD日
|
|
if (/^\d{4}年\d{1,2}月\d{1,2}日$/.test(dateStr)) {
|
|
const year = dateStr.match(/^(\d{4})年/)[1]
|
|
const month = String(dateStr.match(/年(\d{1,2})月/)[1]).padStart(2, '0')
|
|
const day = String(dateStr.match(/月(\d{1,2})日/)[1]).padStart(2, '0')
|
|
return `${year}-${month}-${day}`
|
|
}
|
|
|
|
// 其他格式尝试用Date对象解析
|
|
try {
|
|
const date = new Date(dateStr)
|
|
if (!isNaN(date.getTime())) {
|
|
return this.formatDate(date)
|
|
}
|
|
} catch (error) {
|
|
console.warn('日期格式解析失败:', dateStr, error)
|
|
}
|
|
|
|
// 如果都无法解析,返回原值
|
|
return dateStr
|
|
},
|
|
|
|
// 获取当前日期(用于日期选择器的默认显示)
|
|
getCurrentDate() {
|
|
const today = new Date()
|
|
return this.formatDate(today)
|
|
},
|
|
|
|
// 获取当前日期时间(用于日期时间选择器的默认显示)
|
|
getCurrentDateTime() {
|
|
const now = new Date()
|
|
return this.formatDateTime(now)
|
|
},
|
|
|
|
// 统一的日期时间格式化方法
|
|
formatDateTime(date) {
|
|
const year = date.getFullYear()
|
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
const day = String(date.getDate()).padStart(2, '0')
|
|
const hours = String(date.getHours()).padStart(2, '0')
|
|
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|
|
|
// FirstUI 日期时间选择器支持的格式:YYYY-MM-DD HH:mm
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
|
},
|
|
|
|
// 批量获取字典数据
|
|
async getBatchDictData() {
|
|
try {
|
|
// 定义需要的字典keys
|
|
const dictKeys = [
|
|
'SourceChannel', // 来源渠道
|
|
'source', // 来源
|
|
'customer_purchasing_power', // 购买力
|
|
'preliminarycustomerintention', // 客户初步意向度
|
|
'cognitive_concept', // 认知理念
|
|
'kh_status', // 客户状态
|
|
'decision_maker', // 决策人
|
|
'distance', // 距离
|
|
'emotional_stickiness_score', // 情感粘度
|
|
]
|
|
|
|
// 批量获取字典数据(静默获取,不显示加载提示)
|
|
// 暂时使用简化版本进行测试
|
|
const dictData = await dictUtilSimple.getBatchDict(dictKeys)
|
|
|
|
// 处理字典数据
|
|
this.processDictData(dictData)
|
|
|
|
console.log('批量获取字典数据成功:', dictData)
|
|
|
|
} catch (error) {
|
|
console.error('批量获取字典数据失败:', error)
|
|
|
|
// 如果批量获取失败,回退到单个获取
|
|
await this.fallbackGetDict()
|
|
}
|
|
},
|
|
|
|
// 处理批量获取的字典数据
|
|
processDictData(dictData) {
|
|
// 字典key与本地配置的映射关系
|
|
const keyMapping = {
|
|
'SourceChannel': 'source_channel',
|
|
'source': 'source',
|
|
'customer_purchasing_power': 'purchasing_power',
|
|
'preliminarycustomerintention': 'initial_intent',
|
|
'cognitive_concept': 'cognitive_idea',
|
|
'kh_status': 'status',
|
|
'decision_maker': 'decision_maker',
|
|
'distance': 'distance',
|
|
'emotional_stickiness_score': 'emotional_stickiness_score',
|
|
}
|
|
|
|
// 处理每个字典数据
|
|
Object.keys(keyMapping).forEach(dictKey => {
|
|
const localKey = keyMapping[dictKey]
|
|
const dictItems = dictData[dictKey] || []
|
|
|
|
if (Array.isArray(dictItems) && dictItems.length > 0) {
|
|
const formattedOptions = dictItems.map(item => ({
|
|
text: item.name || '',
|
|
value: item.value || '',
|
|
}))
|
|
|
|
// 设置到picker配置中
|
|
if (this.picker_config[localKey]) {
|
|
this.picker_config[localKey].options = formattedOptions
|
|
}
|
|
}
|
|
})
|
|
},
|
|
|
|
// 回退方案:单个获取字典(兼容原有逻辑)
|
|
async fallbackGetDict() {
|
|
console.log('使用回退方案获取字典数据')
|
|
try {
|
|
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')
|
|
await this.getDict('decision_maker')
|
|
await this.getDict('distance')
|
|
await this.getDict('emotional_stickiness_score')
|
|
} catch (error) {
|
|
console.error('回退方案也失败了:', error)
|
|
}
|
|
},
|
|
async get_campus_list() {
|
|
|
|
let res = await apiRoute.common_getCampusesList({})
|
|
if (res.code != 1) {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
this.campus_list = res.data
|
|
|
|
|
|
let arr = []
|
|
this.campus_list.forEach((v, k) => {
|
|
arr.push({
|
|
text: v.campus_name,
|
|
value: v.id,
|
|
})
|
|
})
|
|
|
|
this.picker_config['campus'].options = arr
|
|
|
|
},
|
|
//获取用户信息
|
|
async getUserInfo() {
|
|
let res = await apiRoute.getPersonnelInfo({})
|
|
if (res.code != 1) {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
this.userInfo = res.data
|
|
|
|
this.formData.consultant = res.data.id//顾问id
|
|
this.formData.staff_id = res.data.id//人员ID
|
|
this.picker_config['consultant'].text = res.data.name//顾问名字
|
|
|
|
await this.get_campus_list()//获取校区
|
|
},
|
|
|
|
|
|
//获取字典
|
|
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 'decision_maker':
|
|
key = 'decision_maker'
|
|
break
|
|
case 'initial_intent':
|
|
key = 'preliminarycustomerintention'
|
|
break
|
|
case 'status':
|
|
key = 'kh_status'
|
|
break
|
|
case 'distance':
|
|
key = 'distance'
|
|
break
|
|
case 'emotional_stickiness_score':
|
|
key = 'emotional_stickiness_score'
|
|
break
|
|
}
|
|
if (!key) {
|
|
return
|
|
}
|
|
// 使用 util.getDict 获取并缓存字典
|
|
let dictionary = await util.getDict(key)
|
|
if (!dictionary || !Array.isArray(dictionary) || dictionary.length === 0) {
|
|
uni.showToast({ title: '暂无选项', icon: 'none' })
|
|
return
|
|
}
|
|
let arr = []
|
|
// 处理接口返回的数据结构 [{name: "抖音", value: "1", sort: 0, memo: ""}, ...]
|
|
dictionary.forEach((v) => {
|
|
arr.push({ text: v.name, value: v.value })
|
|
})
|
|
this.picker_config[inputName].options = arr
|
|
},
|
|
|
|
//##### 查重相关 #####
|
|
//客户列表--查重
|
|
async clientList() {
|
|
|
|
if (!this.student_name) {
|
|
uni.showToast({
|
|
title: '请输入检索关键字',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
this.clientUserList = []
|
|
|
|
let param = {
|
|
name: this.student_name,
|
|
}
|
|
let res = await apiRoute.xs_getAllCustomerResources(param)
|
|
if (res.code != 1) {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
console.log('查重', res)
|
|
this.clientUserList = res.data
|
|
this.openDuplicateCheck()
|
|
},
|
|
//打开结果列表
|
|
openDuplicateCheck() {
|
|
this.showDuplicateCheck = true
|
|
},
|
|
//关闭结果列表
|
|
closeDuplicateCheck(e) {
|
|
this.showDuplicateCheck = false
|
|
},
|
|
|
|
|
|
//跳转页面-客户详情
|
|
openViewClueInfo(item) {
|
|
let resource_sharing_id = ''
|
|
if (item.resourceSharingHasMany && item.resourceSharingHasMany.length > 0) {
|
|
resource_sharing_id = item.resourceSharingHasMany[0].id // 共享资源表id
|
|
}
|
|
|
|
if (!resource_sharing_id) {
|
|
uni.showToast({
|
|
title: '暂时无法查看',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
uni.navigateTo({
|
|
url: `/pages-market/clue/clue_info?resource_sharing_id=${resource_sharing_id}`,
|
|
})
|
|
},
|
|
|
|
//跳转页面-我的消息
|
|
openViewMyMessage(item) {
|
|
let from_id = this.userInfo.id//发送者的id
|
|
let to_id = item.customerResource.id//接收者ID
|
|
uni.navigateTo({
|
|
url: `/pages-common/im_chat_info?from_id=${from_id}&to_id=${to_id}`,
|
|
})
|
|
},
|
|
|
|
//拨打电话
|
|
async dialTel(item) {
|
|
|
|
let tel = item.phone_number
|
|
|
|
if (!tel) {
|
|
uni.showToast({
|
|
title: '电话号码为空',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
|
|
let param = {
|
|
staff_id: this.userInfo.id,//员工id
|
|
resource_id: item.id,//资源ID
|
|
resource_type: '',//资源类型(如设备、文件、系统等)
|
|
communication_type: 'phone',//沟通类型: phone-电话, email-邮件, meeting-会议, other-其他
|
|
communication_result: 'success',//沟通结果: success-成功, failure-失败, pending-待定
|
|
remarks: null,//备注
|
|
tag: null,//标签
|
|
}
|
|
|
|
let res = await apiRoute.xs_communicationRecordsAdd(param)//添加通过记录
|
|
if (res.code != 1) {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
uni.makePhoneCall({
|
|
phoneNumber: tel,
|
|
})
|
|
},
|
|
|
|
|
|
//年龄失去焦点处理 - 计算生日
|
|
handleAgeBlur() {
|
|
if (!this.formData.age) {
|
|
this.formData.birthday = ''
|
|
return
|
|
}
|
|
|
|
const age = parseFloat(this.formData.age)
|
|
|
|
// 验证年龄范围(大于等于0,支持小数)
|
|
if (isNaN(age) || age < 0) {
|
|
uni.showToast({
|
|
title: '年龄请输入大于等于0的数字',
|
|
icon: 'none',
|
|
})
|
|
this.formData.age = ''
|
|
this.formData.birthday = ''
|
|
return
|
|
}
|
|
|
|
// 验证小数位数不超过2位
|
|
const ageStr = this.formData.age.toString()
|
|
if (ageStr.includes('.') && ageStr.split('.')[1].length > 2) {
|
|
uni.showToast({
|
|
title: '年龄小数最多保留2位',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
try {
|
|
// 计算生日
|
|
const today = new Date()
|
|
const currentYear = today.getFullYear()
|
|
const currentMonth = today.getMonth() + 1 // getMonth()返回0-11
|
|
const currentDay = today.getDate()
|
|
|
|
// 计算出生年份和月份
|
|
const yearsOld = Math.floor(age)
|
|
const monthsOld = Math.round((age - yearsOld) * 12)
|
|
|
|
let birthYear = currentYear - yearsOld
|
|
let birthMonth = currentMonth + 3 // 当前月份+3个月
|
|
let birthDay = currentDay
|
|
|
|
// 处理月份超过12的情况
|
|
if (birthMonth > 12) {
|
|
birthYear += 1
|
|
birthMonth -= 12
|
|
}
|
|
|
|
// 如果有额外的月份,需要调整年份
|
|
if (monthsOld > 0) {
|
|
birthMonth -= monthsOld
|
|
if (birthMonth <= 0) {
|
|
birthYear -= 1
|
|
birthMonth += 12
|
|
}
|
|
}
|
|
|
|
// 处理日期边界(避免2月30日等无效日期)
|
|
const maxDaysInMonth = new Date(birthYear, birthMonth, 0).getDate()
|
|
if (birthDay > maxDaysInMonth) {
|
|
birthDay = maxDaysInMonth
|
|
}
|
|
|
|
// 格式化生日
|
|
const formattedMonth = String(birthMonth).padStart(2, '0')
|
|
const formattedDay = String(birthDay).padStart(2, '0')
|
|
this.formData.birthday = `${birthYear}-${formattedMonth}-${formattedDay}`
|
|
|
|
console.log(`年龄: ${age}岁, 计算出的生日: ${this.formData.birthday}`)
|
|
|
|
} catch (error) {
|
|
console.error('计算生日失败:', error)
|
|
uni.showToast({
|
|
title: '生日计算失败,请重新输入',
|
|
icon: 'none',
|
|
})
|
|
this.formData.birthday = ''
|
|
}
|
|
},
|
|
|
|
//联系电话失去焦点时间
|
|
async handlePhoneBlur() {
|
|
if (!this.formData.phone_number) {
|
|
return
|
|
}
|
|
|
|
this.clientUserList = []
|
|
|
|
let param = {
|
|
phone_number: this.formData.phone_number,
|
|
}
|
|
let res = await apiRoute.xs_getAllCustomerResources(param)
|
|
if (res.code != 1) {
|
|
if (res.msg == '暂无数据') {
|
|
return
|
|
}
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
console.log('查重', res)
|
|
this.clientUserList = res.data
|
|
this.openDuplicateCheck()
|
|
},
|
|
|
|
//确认添加学员
|
|
async confirmAddStudent() {
|
|
if (!this.clientUserList || this.clientUserList.length == 0) {
|
|
uni.showToast({
|
|
title: '没有找到重复的用户',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
//取第一个重复用户的ID作为user_id
|
|
const userId = this.clientUserList[0].id
|
|
|
|
//检查必要字段
|
|
if (!this.formData.name) {
|
|
uni.showToast({
|
|
title: '请填写学员姓名',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
if (!this.formData.gender) {
|
|
uni.showToast({
|
|
title: '请选择学员性别',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
//准备学员数据
|
|
const studentData = {
|
|
name: this.formData.name,
|
|
gender: this.formData.gender,
|
|
user_id: userId,
|
|
status: 1,
|
|
}
|
|
|
|
try {
|
|
const res = await apiRoute.xs_addStudent(studentData)
|
|
if (res.code != 1) {
|
|
uni.showToast({
|
|
title: res.msg || '添加学员失败',
|
|
icon: 'none',
|
|
})
|
|
return
|
|
}
|
|
|
|
uni.showToast({
|
|
title: '学员添加成功',
|
|
icon: 'success',
|
|
})
|
|
|
|
//关闭弹窗并跳转回列表页
|
|
this.showDuplicateCheck = false
|
|
setTimeout(() => {
|
|
uni.redirectTo({
|
|
url: `/pages-market/clue/index`,
|
|
})
|
|
}, 1000)
|
|
|
|
} catch (error) {
|
|
console.error('添加学员失败:', error)
|
|
uni.showToast({
|
|
title: '添加学员失败',
|
|
icon: 'none',
|
|
})
|
|
}
|
|
},
|
|
|
|
|
|
//切换tag列表
|
|
async segmented(e) {
|
|
console.log(e)
|
|
//e.id|0=基础信息 1=六要素
|
|
let status = e.id
|
|
this.optionTableId = String(status)
|
|
},
|
|
|
|
|
|
//######-----下拉选择器组件相关-----######
|
|
//打开下拉选择器
|
|
openCicker(input_name, linkage = true) {
|
|
this.picker_options = []
|
|
|
|
this.picker_input_name = input_name
|
|
|
|
let arr = 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) {
|
|
console.log('监听-下拉选择器', this.picker_input_name, e, this.formData)
|
|
let input_name = this.picker_input_name
|
|
this.formData[input_name] = e.value
|
|
this.picker_config[input_name]['text'] = e.text
|
|
|
|
if (input_name == 'source') {
|
|
if (e.value != 1) {
|
|
this.formData.source_channel = '0'//0=线下
|
|
} else {
|
|
this.formData.source_channel = ''//线下
|
|
}
|
|
}
|
|
|
|
// 清空转介绍资源选择,当来源改变时
|
|
if (input_name == 'source') {
|
|
this.clearReferralSelection()
|
|
}
|
|
|
|
this.cancelCicker()
|
|
},
|
|
//关闭下拉选择器
|
|
cancelCicker() {
|
|
this.picker_show = false
|
|
this.picker_input_name = ''
|
|
this.picker_options = []
|
|
},
|
|
|
|
// 转介绍资源搜索功能
|
|
async searchReferralResources() {
|
|
// 清除之前的定时器
|
|
if (this.referralSearchTimer) {
|
|
clearTimeout(this.referralSearchTimer)
|
|
}
|
|
|
|
// 如果搜索关键词为空,清空结果
|
|
if (!this.referralSearchQuery.trim()) {
|
|
this.referralSearchResults = []
|
|
return
|
|
}
|
|
|
|
// 设置防抖定时器
|
|
this.referralSearchTimer = setTimeout(async () => {
|
|
await this.doReferralSearch()
|
|
}, 300) // 300ms防抖
|
|
},
|
|
|
|
// 实际执行搜索的方法
|
|
async doReferralSearch() {
|
|
try {
|
|
// 搜索客户资源 - 优化参数处理
|
|
let param = {}
|
|
const searchQuery = this.referralSearchQuery.trim()
|
|
|
|
// 判断搜索内容是手机号还是姓名
|
|
if (/^1[3-9]\d{9}$/.test(searchQuery)) {
|
|
// 如果是手机号格式,只传递phone_number参数
|
|
param.phone_number = searchQuery
|
|
} else if (/^\d+$/.test(searchQuery)) {
|
|
// 如果是纯数字但不是手机号格式,也当作手机号搜索
|
|
param.phone_number = searchQuery
|
|
} else {
|
|
// 如果包含非数字字符,当作姓名搜索
|
|
param.name = searchQuery
|
|
}
|
|
|
|
let res = await apiRoute.xs_getAllCustomerResources(param)
|
|
if (res.code != 1) {
|
|
if (res.msg !== '暂无数据') {
|
|
uni.showToast({
|
|
title: res.msg,
|
|
icon: 'none',
|
|
})
|
|
}
|
|
this.referralSearchResults = []
|
|
return
|
|
}
|
|
|
|
// 过滤掉当前正在添加的客户(如果手机号相同)
|
|
this.referralSearchResults = (res.data || []).filter(resource => {
|
|
return resource.phone_number !== this.formData.phone_number
|
|
})
|
|
|
|
// 如果没有搜索结果,给用户提示
|
|
if (this.referralSearchResults.length === 0 && searchQuery.length >= 2) {
|
|
// 静默处理,不显示"暂无数据"提示,让用户继续输入
|
|
console.log('未找到匹配的转介绍资源')
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('搜索转介绍资源失败:', error)
|
|
this.referralSearchResults = []
|
|
// 网络错误时给用户提示
|
|
if (this.referralSearchQuery.trim()) {
|
|
uni.showToast({
|
|
title: '搜索失败,请重试',
|
|
icon: 'none',
|
|
})
|
|
}
|
|
}
|
|
},
|
|
|
|
// 选择转介绍资源
|
|
selectReferralResource(resource) {
|
|
this.formData.referral_resource_id = resource.id
|
|
this.selectedReferralResource = resource
|
|
this.referralSearchQuery = ''
|
|
this.referralSearchResults = []
|
|
|
|
uni.showToast({
|
|
title: '已选择转介绍资源',
|
|
icon: 'success',
|
|
})
|
|
},
|
|
|
|
// 清空转介绍资源选择
|
|
clearReferralSelection() {
|
|
this.formData.referral_resource_id = ''
|
|
this.selectedReferralResource = null
|
|
this.referralSearchQuery = ''
|
|
this.referralSearchResults = []
|
|
},
|
|
|
|
|
|
//######-----时间选择器组件相关-----######
|
|
//打开日期选择器
|
|
openDate(input_name) {
|
|
console.log('打开日期选择器:', input_name)
|
|
this.data_picker_input_name = input_name
|
|
|
|
// 设置日期选择器显示
|
|
this.$nextTick(() => {
|
|
this.date_picker_show = true
|
|
})
|
|
},
|
|
|
|
//打开日期时间选择器
|
|
openDateTime(input_name) {
|
|
console.log('打开日期时间选择器:', input_name)
|
|
this.datetime_picker_input_name = input_name
|
|
|
|
// 设置日期时间选择器显示
|
|
this.$nextTick(() => {
|
|
this.datetime_picker_show = true
|
|
})
|
|
},
|
|
//选择跟进时间
|
|
change_date(e) {
|
|
console.log('日期选择器返回数据:', e)
|
|
|
|
// 获取选择的日期值,兼容不同的返回格式
|
|
let val = ''
|
|
if (e.result) {
|
|
val = e.result
|
|
} else if (e.value) {
|
|
val = e.value
|
|
} else if (e.detail && e.detail.result) {
|
|
val = e.detail.result
|
|
} else if (e.detail && e.detail.value) {
|
|
val = e.detail.value
|
|
}
|
|
|
|
// 确保日期格式为 YYYY-MM-DD
|
|
if (val && typeof val === 'string') {
|
|
// 如果是时间戳,转换为日期字符串
|
|
if (/^\d+$/.test(val)) {
|
|
const date = new Date(parseInt(val))
|
|
val = this.formatDate(date)
|
|
}
|
|
// 如果包含时间部分,只保留日期部分
|
|
else if (val.includes(' ')) {
|
|
val = val.split(' ')[0]
|
|
}
|
|
// 统一格式为 YYYY-MM-DD
|
|
if (val.includes('/')) {
|
|
const parts = val.split('/')
|
|
if (parts.length === 3) {
|
|
val = `${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`
|
|
}
|
|
}
|
|
}
|
|
|
|
let input_name = this.data_picker_input_name
|
|
this.formData[input_name] = val
|
|
|
|
console.log(`设置${input_name}为:`, val)
|
|
this.cancel_date()
|
|
},
|
|
//关闭选择跟进时间
|
|
cancel_date() {
|
|
this.date_picker_show = false
|
|
},
|
|
|
|
//选择日期时间
|
|
change_datetime(e) {
|
|
console.log('日期时间选择器返回数据:', e)
|
|
|
|
// 获取选择的日期时间值,兼容不同的返回格式
|
|
let val = ''
|
|
if (e.result) {
|
|
val = e.result
|
|
} else if (e.value) {
|
|
val = e.value
|
|
} else if (e.detail && e.detail.result) {
|
|
val = e.detail.result
|
|
} else if (e.detail && e.detail.value) {
|
|
val = e.detail.value
|
|
}
|
|
|
|
// 确保日期时间格式为 YYYY-MM-DD HH:mm
|
|
if (val && typeof val === 'string') {
|
|
// 如果是时间戳,转换为日期时间字符串
|
|
if (/^\d+$/.test(val)) {
|
|
const date = new Date(parseInt(val))
|
|
val = this.formatDateTime(date)
|
|
}
|
|
// 统一格式为 YYYY-MM-DD HH:mm
|
|
if (val.includes('/')) {
|
|
// 处理 YYYY/MM/DD HH:mm 格式
|
|
val = val.replace(/\//g, '-')
|
|
}
|
|
}
|
|
|
|
let input_name = this.datetime_picker_input_name
|
|
this.formData[input_name] = val
|
|
|
|
console.log(`设置${input_name}为:`, val)
|
|
this.cancel_datetime()
|
|
},
|
|
|
|
//关闭日期时间选择器
|
|
cancel_datetime() {
|
|
this.datetime_picker_show = false
|
|
},
|
|
|
|
|
|
//下一步 index|0=添加客户,1六要素
|
|
async nextStep(index) {
|
|
this.optionTableId = String(index)
|
|
},
|
|
//表单验证
|
|
async validatorForm(data) {
|
|
//姓名
|
|
if (!data.name) {
|
|
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.campus) {
|
|
uni.showToast({
|
|
title: '校区必填',
|
|
icon: 'none',
|
|
})
|
|
this.nextStep('0')
|
|
return false
|
|
}
|
|
|
|
//转介绍资源必填(当来源为转介绍时)
|
|
if (data.source == 3 && !data.referral_resource_id) {
|
|
uni.showToast({
|
|
title: '请选择转介绍资源',
|
|
icon: 'none',
|
|
})
|
|
this.nextStep('0')
|
|
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.redirectTo({
|
|
url: `/pages-market/clue/index`,
|
|
})
|
|
}, 1000)
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.search_box {
|
|
padding: 20rpx 40rpx;
|
|
border-bottom: 1px solid #333333;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.input_box {
|
|
width: 70%;
|
|
|
|
input {
|
|
width: 100%;
|
|
height: 60rpx;
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
}
|
|
}
|
|
|
|
.btn {
|
|
font-size: 28rpx;
|
|
color: #24BA9F;
|
|
}
|
|
}
|
|
|
|
.assemble {
|
|
width: 100%;
|
|
height: 100vh;
|
|
background: #292929;
|
|
overflow: auto;
|
|
}
|
|
|
|
.title {
|
|
font-size: 26rpx;
|
|
color: #fff;
|
|
padding: 26rpx 0 26rpx 32rpx;
|
|
}
|
|
|
|
.input-title {
|
|
font-size: 26rpx;
|
|
color: #fff;
|
|
}
|
|
|
|
.form-style {
|
|
width: 100%;
|
|
}
|
|
|
|
.input-style {
|
|
text-align: right !important;
|
|
}
|
|
|
|
.fui-btn__box {
|
|
margin: 50rpx auto 120rpx;
|
|
width: 92%;
|
|
}
|
|
|
|
//查重结构弹出层
|
|
.fui-scroll__wrap {
|
|
height: 60vh;
|
|
|
|
.title_box {
|
|
padding: 10rpx 20rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.title {
|
|
font-size: 28rpx;
|
|
color: #101010;
|
|
}
|
|
}
|
|
|
|
.section_ul {
|
|
margin-bottom: 100rpx;
|
|
height: 98%;
|
|
|
|
.not_list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.img {
|
|
width: 112rpx;
|
|
height: 112rpx;
|
|
}
|
|
|
|
.title {
|
|
padding: 0;
|
|
margin-top: 10rpx;
|
|
color: #101010;
|
|
font-size: 28rpx;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.ul {
|
|
padding: 26rpx;
|
|
padding-bottom: 100rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
|
|
.li {
|
|
margin-bottom: 26rpx;
|
|
padding: 26rpx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 10rpx;
|
|
|
|
border-radius: 18rpx;
|
|
background-color: rgba(67, 69, 68, 1);
|
|
color: #fff;
|
|
font-size: 28rpx;
|
|
border: 0rpx solid rgba(121, 121, 121, 1);
|
|
|
|
.left_box {
|
|
width: 80%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20rpx;
|
|
|
|
.box_1 {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.img {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.name {
|
|
margin-left: 20rpx;
|
|
}
|
|
}
|
|
|
|
.box_2 {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.left {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
|
|
.name {
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.call {
|
|
margin-left: 10rpx;
|
|
font-size: 24rpx;
|
|
color: #ba7b30;
|
|
}
|
|
}
|
|
}
|
|
|
|
.box_3 {
|
|
display: flex;
|
|
gap: 30rpx;
|
|
|
|
.right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10rpx;
|
|
|
|
.img {
|
|
width: 16rpx;
|
|
height: 16rpx;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.right_box {
|
|
width: 25%;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
.img {
|
|
width: 70rpx;
|
|
height: 70rpx;
|
|
border-radius: 50%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// 快速填写弹窗样式
|
|
.quick-fill-mask {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: rgba(0, 0, 0, 0.6);
|
|
z-index: 1500;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 40rpx;
|
|
}
|
|
|
|
.quick-fill-content {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
width: 100%;
|
|
max-width: 600rpx;
|
|
max-height: 80vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.quick-fill-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 32rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.quick-fill-title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333;
|
|
}
|
|
|
|
.quick-fill-close {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
.close-text {
|
|
font-size: 32rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.duplicate-notice {
|
|
padding: 32rpx;
|
|
text-align: center;
|
|
border-bottom: 1px solid #eee;
|
|
margin-bottom: 20rpx;
|
|
|
|
text {
|
|
display: block;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
}
|
|
|
|
.quick-fill-body {
|
|
padding: 32rpx;
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.quick-fill-tip {
|
|
margin-bottom: 24rpx;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
line-height: 1.5;
|
|
|
|
text:first-child {
|
|
display: block;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
text:last-child {
|
|
display: block;
|
|
color: #29d3b4;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
|
|
.quick-fill-textarea {
|
|
width: 100%;
|
|
height: 300rpx;
|
|
border: 1px solid #ddd;
|
|
border-radius: 8rpx;
|
|
padding: 16rpx;
|
|
font-size: 28rpx;
|
|
line-height: 1.5;
|
|
background: #fafafa;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.quick-fill-buttons {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
padding: 32rpx;
|
|
border-top: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.quick-fill-btn {
|
|
flex: 1;
|
|
height: 72rpx;
|
|
line-height: 72rpx;
|
|
text-align: center;
|
|
border-radius: 8rpx;
|
|
font-size: 28rpx;
|
|
font-weight: 600;
|
|
|
|
&.cancel-btn {
|
|
background: #f5f5f5;
|
|
color: #666;
|
|
border: 1px solid #ddd;
|
|
}
|
|
|
|
&.confirm-btn {
|
|
background: #29d3b4;
|
|
color: #fff;
|
|
}
|
|
}
|
|
|
|
// 转介绍资源选择相关样式
|
|
.referral-search-container {
|
|
position: relative;
|
|
|
|
.referral-search-results {
|
|
position: absolute;
|
|
top: 100%;
|
|
left: 0;
|
|
right: 0;
|
|
background: #333;
|
|
border-radius: 8rpx;
|
|
border: 1px solid #555;
|
|
max-height: 400rpx;
|
|
overflow-y: auto;
|
|
z-index: 100;
|
|
margin-top: 8rpx;
|
|
|
|
.referral-search-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20rpx;
|
|
border-bottom: 1px solid #555;
|
|
transition: background-color 0.2s;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&:hover, &.selected {
|
|
background: #434544;
|
|
}
|
|
|
|
.resource-info {
|
|
flex: 1;
|
|
|
|
.resource-name {
|
|
font-size: 28rpx;
|
|
color: #fff;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.resource-phone {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.check-icon {
|
|
color: #29d3b4;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
}
|
|
}
|
|
}
|
|
|
|
.selected-referral-resource {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16rpx;
|
|
background: #4a4a4a;
|
|
border-radius: 8rpx;
|
|
margin-top: 8rpx;
|
|
|
|
.selected-resource-info {
|
|
flex: 1;
|
|
|
|
.selected-resource-name {
|
|
font-size: 28rpx;
|
|
color: #29d3b4;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.selected-resource-phone {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
|
|
.clear-selection {
|
|
color: #f44336;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
padding: 8rpx;
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
}
|
|
</style>
|