Files
crm-uni/pages/customer/followup.vue
T
2025-03-18 13:32:13 +08:00

481 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<uni-nav-bar leftText=" " :fixed="true" :border="false" leftIcon="back" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="添加跟进"></uni-nav-bar>
<view class="content">
<view class="cell">
<view>跟进方式</view>
<view class="right">
<u-radio-group v-model="form.type">
<u-radio name="1">在线跟进</u-radio>
<u-radio name="0">拜访</u-radio>
</u-radio-group>
</view>
</view>
<u-line></u-line>
<view class="cell">
<view>跟进时间</view>
<view class="right" @click="show = true">
<input placeholder="跟进时间" v-model="form.firstFollowtime" />
</view>
</view>
<u-line></u-line>
<view class="cell1" v-if="form.type==1">
<view>上传跟进最后聊天截图</view>
<view style="margin-top: 10px;">
<uni-file-picker fileMediatype="image" limit="1" :del-icon="false" disable-preview @select="select" @delete="delfn('picture')">
<image src="/static/image/customer/upimg.png" mode="" class="addimg"></image>
</uni-file-picker>
</view>
</view>
<view class="cell" v-if="form.type==0">
<view>当前位置</view>
<view class="right">
<input placeholder="输入当前位置" v-model="form.address" />
</view>
</view>
<u-line v-if="form.type==0"></u-line>
<view class="cell1" v-if="form.type==0">
<view>当前位置拍照上传</view>
<view style="margin-top: 10px;">
<uni-file-picker fileMediatype="image" limit="1" :del-icon="false" disable-preview @select="select1" @delete="delfn('picture')">
<image src="/static/image/customer/upimg.png" mode="" class="addimg"></image>
</uni-file-picker>
</view>
</view>
<u-line v-if="form.type==0"></u-line>
<view class="cell1" v-if="form.type==0">
<view>拜访内容</view>
<view class="yuyin">
<textarea auto-height v-model="form.audio_text" placeholder="拜访内容..."/>
<image src="/static/image/customer/yuyin.png" mode="" @tap="startRecognizebd"></image>
</view>
</view>
<u-line v-if="form.type==0"></u-line>
<view class="cell1" v-if="form.type==0">
<view>备注(非必填)</view>
<view class="yuyin">
<textarea auto-height v-model="form.remark" placeholder="详细情况..."/>
<image src="/static/image/customer/yuyin.png" mode="" @tap="startRecognize"></image>
</view>
</view>
</view>
<u-gap height="10" bgColor="#F6F6F6"></u-gap>
<view class="steps">
<view class="title">
跟进记录 <text class="status">跟进中</text>
</view>
<u-steps v-if="followList.length>0" :current="followList.length" direction="column" dot>
<u-steps-item :title="item.type_txt" v-for="(item, index) in followList" :key="index">
<view slot="desc" class="desc">
<view class="" v-if="item.type==0">
<view class="">
<view class="">
时间:{{item.created_at}}
</view>
<view class="">地址:{{item.address}}</view>
<view class="">拜访内容:{{item.audio_text}}</view>
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
</view>
</view>
<view class="" v-else>
<view class="">
时间:{{item.created_at}}
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
</view>
</view>
</view>
</u-steps-item>
</u-steps>
<empty :list="followList"></empty>
</view>
<u-gap height="100" bgColor="#fff"></u-gap>
<view class="foot">
<button class="btn1" @click="shownexttime=true">下次跟进提醒</button>
<button class="btn" @click="nextFn">提交</button>
</view>
<u-datetime-picker
:show="show"
v-model="firstFollow"
mode="datetime"
@confirm="confirm"
@cancel="cancel"
@change="change"
></u-datetime-picker>
<u-datetime-picker
:show="shownexttime"
v-model="nexttime"
mode="datetime"
@confirm="confirmnext"
@cancel="cancelnext"
></u-datetime-picker>
</view>
</template>
<script>
import permision from "@/common/permission.js"
import { request,showToast } from '@/api/apiT.js'
export default {
data() {
return {
id:'',
show:false,
shownexttime:false,
firstFollow: Number(new Date()),
nexttime: Number(new Date()),
followList:[],
form: {
customer_id:'',
type: '1',
address: '',
lat: '',
lng: '',
firstFollowtime:'',
audio_text:'',
remark:'',
picture:''
}
}
},
onLoad(options) {
console.log(options);
this.id = options.id;
this.form.customer_id = options.id;
var that = this
this.getlocahost()
this.followlistfn()
},
methods: {
leftClick(){
uni.navigateBack({})
},
// 获取当前位置
getarrd(longitude,latitude){
const apiKey = 'AIzaSyBGvV-vX7C72PEbcYrTdmUj3qrubejWzNw';
uni.request({
url: `https://www.google.com/maps/embed/v1/view?key=${apiKey}&location=${longitude},${latitude}`,
success: (res) => {
console.log('逆地理编码结果:', res.data);
if (res.data.status === '1') {
const address = res.data.regeocode.formatted_address; // 具体地址
console.log('具体地址:', address);
}
},
fail: (err) => {
console.log('逆地理编码失败:', err);
}
});
},
getlocahost(){
uni.getLocation({
type: 'wgs84', // 默认为 wgs84 坐标系,可选 gcj02
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
getarrd(res.longitude,res.latitude)
// 如果需要将经纬度转换为具体地址,可以使用逆地理编码
// 这里调用 uni.chooseLocation 或第三方地图服务(如高德、腾讯地图)
},
fail: function (err) {
console.log('获取位置失败:', err);
},
complete: function () {
console.log('获取位置完成');
}
});
// uni.chooseLocation({
// success: function (res) {
// console.log('位置名称:' + res.name);
// console.log('详细地址:' + res.address);
// console.log('经度:' + res.longitude);
// console.log('纬度:' + res.latitude);
// },
// fail: function (err) {
// console.log('选择位置失败:', err);
// }
// });
},
// 跟进记录
followlistfn(){
request({
url:'follow/list',
method:'get',
data: {
customer_id:this.id,
}
}).then(res => {
this.followList = res.data.data
console.log(res.data.data)
})
},
//保存跟进
nextFn(){
request({
url:'follow/save',
method:'post',
data:this.form
}).then(res => {
uni.showToast({
title: res.data.message,
icon: 'none'
});
if(res.data.code ==0){
// setTimeout(() => {
// uni.reLaunch({
// url: '/pages/index/index',// 替换为你要跳转的页面路径
// });
// }, 1000);
}
})
},
result(time, mode) {
const timeFormat = uni.$u.timeFormat
switch (mode) {
case 'datetime':
return timeFormat(time, 'yyyy-mm-dd hh:MM')
case 'date':
return timeFormat(time, 'yyyy-mm-dd')
case 'year-month':
return timeFormat(time, 'yyyy-mm')
case 'time':
return time
default:
return ''
}
},
cancel() {
this.show = false
},
confirm(e) {
this.show = false
this.form.firstFollowtime = this.result(e.value, e.mode)
console.log(this.result(e.value, e.mode))
},
cancelnext() {
this.shownexttime = false
},
confirmnext(e) {
this.shownexttime = false
this.nexttime = this.result(e.value, e.mode)
console.log(this.nexttime)
},
change(e) {
// console.log('change', e)
},
delfn(name){
console.log(name)
that.carinfo[name] =''
},
uploadfn(imgUrl,name){
var that = this;
uni.uploadFile({
url: 'http://192.168.50.4:8787/upload',
filePath: imgUrl,
name: 'files',
header:{'content-type': 'application/x-www-form-urlencoded','Authorization': 'Bearer ' + uni.getStorageSync('token')},
success: (uploadFileRes) => {
const path=JSON.parse(uploadFileRes.data)
that.form[name] = path.data.path
console.log(that.form)
}
});
},
select(e){
const tempFilePaths = e.tempFilePaths;
const imgUrl=tempFilePaths[0]
this.uploadfn(imgUrl,'picture')
},
select1(e){
const tempFilePaths = e.tempFilePaths;
const imgUrl=tempFilePaths[0]
this.uploadfn(imgUrl,'picture')
},
async startRecognizebd () {
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
// TODO ios 在没有请求过权限之前无法得知是否有相关权限,这种状态下需要直接调用语音,会弹出正在识别的toast
var options = {};
var that = this;
options.engine = 'baidu';
that.form.bf_desc = "";
plus.speech.startRecognize(options, function (s) {
console.log(s);
that.form.bf_desc += s;
}, function (e) {
console.log("语音识别失败:" + e.message);
});
},
async startRecognize () {
// #ifdef APP-PLUS
let status = await this.checkPermission();
if (status !== 1) {
return;
}
// #endif
// TODO ios 在没有请求过权限之前无法得知是否有相关权限,这种状态下需要直接调用语音,会弹出正在识别的toast
var options = {};
var that = this;
that.form.mom_desc = "";
options.engine = 'iFly';
options.punctuation = false; // 是否需要标点符号
options.timeout = 10 * 1000; //语音录入持续时长
plus.speech.startRecognize(options, function(s) {
console.log(s);
that.form.mom_desc += s;
// 关闭语音
plus.speech.stopRecognize();
}, function (e) {
console.log("语音识别失败:" + e.message);
});
},
// #ifdef APP-PLUS
async checkPermission() {
let status = permision.isIOS ? await permision.requestIOS('record') :
await permision.requestAndroid('android.permission.RECORD_AUDIO');
if (status === null || status === 1) {
status = 1;
} else if (status === 2) {
uni.showModal({
content: "系统麦克风已关闭",
confirmText: "确定",
showCancel: false,
success: function(res) {
}
})
} else {
uni.showModal({
content: "需要麦克风权限",
confirmText: "设置",
success: function(res) {
if (res.confirm) {
permision.gotoAppSetting();
}
}
})
}
return status;
}
// #endif
}
}
</script>
<style lang="scss">
textarea {
min-height: 200rpx;// 设置默认高度 ,解决设置自适应高度之后高度无效问题
margin-top: 15px;
background-color: #F6F6F6;
padding: 15px;
border-radius: 10px;
}
.u-divider{
margin: 0px 0px !important;
}
.content{
padding-top: 10px;
background: #FFFFFF;
// height: calc(100vh - 44px);
}
.cell{
position: relative;
display: flex;
justify-content:space-between;
padding: 18px 20px;
align-items: center;
font-size: 32rpx;
font-weight: 500;
font-size: 32rpx;
color: #666666;
}
.arrowright{
margin-right: -15px;
}
.cell1{
font-size: 32rpx;
padding: 18px 20px;
align-items: center;
font-weight: 500;
color: #666666;
}
.right{
text-align: right;
color: #222222;
}
.foot{
position: fixed;
bottom: 0px;
width: 100%;
height: 90px;
background: #FFFFFF;
z-index: 1;
display: flex;
padding-top: 20px;
}
.btn{
background: linear-gradient(to right, #3471FF, #6776FF);
color: white;
border-radius: 50px;
width: 45%;
height: 96rpx;
line-height: 96rpx;
margin-top: 20px;
}
.btn1{
border: 1px solid #3471FF;
background: #fff;
color: #3471FF;
border-radius: 50px;
width: 45%;
height: 96rpx;
line-height: 96rpx;
margin-top: 20px;
}
.addimg{
width: 110px;
height:110px;
}
.yuyin{
position: relative;
image{
width: 20px;
height:24px;
position: absolute;
right: 15px;
bottom: 10px;
}
}
.steps{
padding: 15px;
image{
width: 44px;
height:44px;
}
.desc{
display: flex;
justify-content: space-between;
align-items: center;
color: #999999;
}
.title{
color: #666666;
font-size: 32rpx;
margin-bottom: 15px;
.status{
font-size: 28rpx;
color: #3471FF;
margin-left: 10px;
}
}
}
</style>