标签功能

This commit is contained in:
浅念
2025-03-27 16:13:47 +08:00
parent 8583ff2543
commit 526f934a75
11 changed files with 343 additions and 233 deletions
+1
View File
@@ -1,6 +1,7 @@
// const baseUrl = "http://219.157.255.213:9007/"; //这里放置url域名32044
// const baseUrl = "http://api.crm.hnxinyouhe.com/"; //这里放置url域名32044
// const baseUrl = "http://192.168.50.9:8787/"; //这里放置url域名32044
const baseUrl = "http://219.157.255.213:25329/"; //这里放置url域名32044
// const baseUrl = "/api/"; //这里放置url域名32044
export function request(options){//封装的requset
+6 -1
View File
@@ -175,5 +175,10 @@ export default {
nextgjtime:'Next follow up time',
Remindergj:'Follow up reminder',
callPhonemsg:'Dial the wrong number!',
download:'Download'
download:'Download',
addtag:'Add labels',
CustomerProfile:'Customer Profile',
CustomerProfilemag:'No portrait label!',
retract:'Retract',
expand:'Expand to view more'
}
+6 -1
View File
@@ -174,5 +174,10 @@ export default {
nextgjtime:'下次跟进时间',
Remindergj:'跟进提醒',
callPhonemsg:'拨打号码错误!',
download:'下载'
download:'下载',
addtag:'添加标签',
CustomerProfile:'客户画像',
CustomerProfilemag:'暂无画像标签!',
retract:'收起',
expand:'展开查看更多'
}
+2 -145
View File
@@ -77,14 +77,6 @@
</view>
</view>
<u-line></u-line>
<view class="cell">
<view class="item">{{$t('customer.Cstomertag')}}</view>
<view class="right select" @click="showtag = true">
<view class="" :class="['content2', { placeholder: !grade_name }]">{{grade_name || $t('customer.Cstomertaginput')}}</view>
<u-icon class="arrowright" name="arrow-right" size="18" color="#747474"></u-icon>
</view>
</view>
<u-line></u-line>
<view class="cell">
<view class="item">{{$t('customer.Country')}}</view>
<view class="right select" @click="showarea = true">
@@ -157,26 +149,7 @@
</scroll-view>
</view>
</u-popup>
<!-- 客户标签 -->
<u-popup closeOnClickOverlay :show="showtag" mode="bottom" :round="10" title="客户标签" @close="close('showtag')" :closeable="true" >
<view class="popup-content">
<scroll-view scroll-y class="tag-list">
<view
v-for="(item, index) in taglist"
:key="index"
class="tags"
>
<view class="name">{{ item.name }}</view>
<view class="row">
<view class="col4 tagitem" v-for="(item1, index1) in item.child" :class="{ 'tagactive': isActive(item1.pid, item1.id) }" @click="tagSelect(item1)" :key="index1">
{{ item1.name }}
</view>
</view>
</view>
</scroll-view>
</view>
</u-popup>
</view>
</template>
<script>
@@ -224,85 +197,7 @@
},
location:{},
activeMap: {}, // 存储每个父级下选中的子项 { 父ID: 子ID }
taglist:[
{
name:'客户价值',
id:'1',
child:[
{name:'高价值',id:1,pid:1},
{name:'中价值',id:2,pid:1},
{name:'低价值',id:3,pid:1},
{name:'潜在高价值',id:4,pid:1},
]
},
{
name:'生命周期',
id:'2',
child:[
{name:'新客户',id:5,pid:2},
{name:'活跃',id:6,pid:2},
{name:'沉默',id:7,pid:2},
{name:'流失',id:8,pid:2},
]
},
{
name:'行为标签',
id:'3',
child:[
{name:'高频购买',id:9,pid:3},
{name:'大单',id:10,pid:3},
{name:'促销敏感',id:11,pid:3},
{name:'忠诚',id:12,pid:3},
]
},
{
name:'需求标签',
id:'4',
child:[
{name:'价格敏感',id:13,pid:4},
{name:'品质追求',id:14,pid:4},
{name:'服务',id:15,pid:4},
{name:'定制化',id:16,pid:4},
]
},
{
name:'来源标签',
id:'5',
child:[
{name:'线上',id:17,pid:5},
{name:'线下',id:18,pid:5},
{name:'推荐',id:19,pid:5},
{name:'合作伙伴',id:20,pid:5},
]
},
{
name:'风险标签',
id:'6',
child:[
{name:'高',id:21,pid:6},
{name:'中',id:22,pid:6},
{name:'低',id:23,pid:6},
]
},
{
name:'满意度标签',
id:'7',
child:[
{name:'高',id:24,pid:7},
{name:'中',id:25,pid:7},
{name:'低',id:26,pid:7},
]
},
{
name:'忠诚度标签',
id:'8',
child:[
{name:'高',id:27,pid:8},
{name:'中',id:28,pid:8},
{name:'低',id:29,pid:8},
]
}
]
taglist:[]
}
},
onLoad() {
@@ -464,13 +359,6 @@
close(val){
this[val] = false
},
//标签点击
tagSelect(item) {
this.$set(this.activeMap, item.pid, item.id);
},
isActive(parentId, childId) {
return this.activeMap[parentId] === childId;
},
//提交保存
saveFn(){
if(this.form.contacts==''){
@@ -642,35 +530,4 @@
color: #999;
}
// 标签弹框
.tag-list{
max-height: 900rpx;
margin-top: 20rpx;
.tags{
margin-top: 10px;
}
.name{
margin: 10px 0px;
}
.tagitem{
background: #ECF2FF;
border-radius: 8px;
color: #3471FF;
text-align: center;
padding: 5px 0px;
}
.row{
width: 100%;
}
.col4{
display: inline-block;
margin: 4px 3px;
width: 30%;
}
}
.tagactive{
background: #3471FF !important;
color: #fff !important;
}
</style>
+198 -39
View File
@@ -24,24 +24,32 @@
<view v-if="datas.describe!=''">备注: {{datas.describe}}</view>
</view>
<view class="edt">
<!-- <view class="btn" @click="showtag = true"><image src="/static/image/customer/tagadd.png" mode=""></image><text> {{$t('addtag')}}</text></view> -->
<view class="btn" @click="editFn"><image src="/static/image/customer/edit.png" mode=""></image><text> {{$t('edtbtn')}}</text></view>
</view>
</view>
<view class="cells">
<u-collapse :border="false">
<u-collapse-item
title="标签"
name="Docs guide"
:border="false"
>
<view class="">
<view class="tags">潜在高价值</view>
<view class="tags">活跃客户</view>
<view class="tags">促销敏感</view>
<view class="tags">促销敏</view>
</view>
</u-collapse-item>
</u-collapse>
<view class="top">
<view class="item">{{$t('CustomerProfile')}}</view>
<view class="right">
<view class="btn"@click="showtag = true"><image src="/static/image/customer/tagadd.png" mode=""></image><text> {{$t('addtag')}}</text></view>
</view>
</view>
<view v-if="datas.tags.length>0">
<view class="conts" :class="{'expandeds':!expanded}">
<view class="tags" v-for="(item, index) in datas.tags" :key="index">{{item.name}}</view>
</view>
<view class="toggle" @click="expanded = !expanded">
<text >
{{ expanded ? $t('retract') : $t('expand') }}
</text>
<u-icon v-if="expanded" class="arrowright" name="arrow-up" size="16" color="#999999"></u-icon>
<u-icon v-else class="arrowright" name="arrow-down" size="16" color="#999999"></u-icon>
</view>
</view>
<view v-else class="nones">
{{$t('CustomerProfilemag')}}
</view>
</view>
<view class="cell">
<view class="item">{{$t('customer.Cstomerfj')}}</view>
@@ -65,24 +73,34 @@
<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="flex" v-if="item.type==0">
<view class="">
<view class="">
<view class="lingh">
{{$t('times')}} :{{item.created_at}}
</view>
<view class="">{{$t('address')}}:{{item.address}}</view>
<view class="">{{$t('customer.Visitcontent')}}:{{item.audio_text}}</view>
<view class="lingh">{{$t('customer.Visitcontent')}}:{{item.audio_text}}</view>
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
<!-- <image :src="item.oss_picture" mode=""></image> -->
<u-album
:urls="isurls(item.oss_picture)"
:singleSize="80"
keyName="src"
></u-album>
</view>
</view>
<view class="" v-else>
<view class="">
<view class="lingh">
{{$t('times')}}:{{item.created_at}}
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
<u-album
:urls="isurls(item.oss_picture)"
keyName="src"
:singleSize="80"
></u-album>
<!-- <image :src="item.oss_picture" mode=""></image> -->
</view>
</view>
</view>
@@ -91,23 +109,27 @@
<empty :list="followList"></empty>
</view>
<view class="zw"></view>
<!-- <view class="foot">
<button class="btn" @click="nextFn">{{$t('submit')}}</button>
</view> -->
<u-picker closeOnClickOverlay :cancel-text="$t('cancel')" :confirm-text="$t('confirm')" :defaultIndex="defaultIndexfj" :show="showgrade" @cancel="cancel('showgrade')" @close="close('showgrade')" :columns="getGradeList" keyName="name" @confirm="gradeHandler"></u-picker>
<!-- <u-popup :show="showmap" :round="10" mode="bottom" @close="mapclose">
<view class="mapcont">
<view class="header">
<view class="cancel" @click="mapclose">取消</view>
<view class="title">地图位置</view>
<view class="confirm" @click="mapconfirm">确定</view>
</view>
<view class="map">
<!-- 客户标签 -->
<u-popup closeOnClickOverlay :show="showtag" mode="bottom" :round="10" @close="closetag('showtag')" :closeable="true" >
<view class="popup-content">
<scroll-view scroll-y class="tag-list">
<view
v-for="(item, index) in taglist"
:key="index"
class="tags"
>
<view class="name">{{ item.name }}</view>
<view class="row">
<view class="col4 tagitem" v-for="(item1, index1) in item.tags" :class="{ 'tagactive': isActive(item1.group_id, item1.id) }" @click="tagSelect(item1)" :key="index1">
{{ item1.name }}
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</u-popup> -->
</u-popup>
</view>
</template>
@@ -117,7 +139,9 @@
data() {
return {
id:'',
expanded:false,
followList:[],
showtag: false,
showmap: false,
showmagnitude: false,
showgrade: false,
@@ -131,7 +155,9 @@
form: {
grade:'',
},
datas:''
datas:'',
activeMap: {}, // 存储每个父级下选中的子项 { 父ID: 子ID }
taglist:[]
}
},
@@ -141,6 +167,7 @@
var that = this
this.getGrade()
this.customerdetailfn()
this.tagGroup()
},
onShow() {
@@ -157,6 +184,13 @@
leftClick(){
uni.navigateBack({})
},
isurls(url){
var urls=[]
var obj={}
obj.src = url
urls.push(obj)
return urls
},
gomap(){
uni.navigateTo({
url: '/pages/customer/map'
@@ -182,6 +216,10 @@
}
}).then(res => {
that.datas = res.data.data
that.datas.tags.forEach((item,index) => {
that.$set(that.activeMap, item.group_id,item.id);
})
that.form = res.data.data
that.select()
})
@@ -254,11 +292,49 @@
close(val){
this[val] = false
},
closetag(val){
this[val] = false
this.customerdetailfn()
},
editFn(){
uni.navigateTo({
url: '/pages/customer/editdetile?id='+this.id
});
},
//标签
tagGroup(){
request({
url:'tagGroup/list',
method:'get',
}).then(res => {
this.taglist = res.data.data
})
},
//标签点击
tagSelect(item) {
// 如果已选中则取消,否则设置选中
this.$set(this.activeMap, item.group_id, this.activeMap[item.group_id] === item.id ? '' : item.id);
console.log(this.activeMap)
request({
url:'tagGroup/updatePivot',
method:'post',
data:{
customer_id: this.id,
group_id:item.group_id,
tag_id:this.activeMap[item.group_id]
}
}).then(res => {
if(res.data.code!=0){
uni.showToast({
title: res.data.message,
icon: 'none'
});
}
})
},
isActive(parentId, childId) {
return this.activeMap[parentId] === childId;
},
nextFn(){
request({
url:'customer/save',
@@ -316,20 +392,61 @@
position: absolute;
top: 2px;
}
.expandeds{
height: 33px;
overflow: hidden;
}
.cells{
margin-bottom: 10px;
background: #f6f6f6;
padding:13px 15px;
border-radius: 10px;
.top{
display: flex;
align-items: center;
justify-content: space-between;
color: #666666;
}
.btn{
color: #3471FF;
text-align: right;
display: flex;
align-items: center;
}
image{
width: 14px;
height: 14px;
margin-right: 5px;
}
.conts{
padding: 10px 0px;
}
.tags{
display: inline-block;
margin: 4px 3px;
width: 31%;
// width: 31%;
background: #ECF2FF;
border-radius: 15px;
color: #3471FF;
text-align: center;
padding: 5px 0px;
padding: 5px 15px;
}
.toggle{
display: flex;
align-items: center;
justify-content: center;
color: #999999;
font-size: 12px;
margin-top: 5px;
text{
margin-right: 5px;
}
}
.nones{
text-align: center;
color: #999999;
line-height: 30px;
font-size: 12px;
}
}
.cell{
@@ -372,6 +489,7 @@
display: flex;
justify-content: right;
padding-bottom: 10px;
text-align: center;
image{
width: 14px;
height: 14px;
@@ -448,10 +566,17 @@
height:44px;
}
.desc{
display: flex;
justify-content: space-between;
align-items: center;
color: #999999;
.lingh{
line-height: 40px;
}
.flex{
display: flex;
justify-content: space-between;
align-items: center;
}
}
.title{
display: flex;
@@ -473,4 +598,38 @@
}
}
}
// 标签弹框
.popup-content {
padding: 20px;
}
.tag-list{
max-height: 900rpx;
margin-top: 20rpx;
.tags{
margin-top: 10px;
}
.name{
margin: 10px 0px;
}
.tagitem{
background: #ECF2FF;
border-radius: 8px;
color: #3471FF;
text-align: center;
padding: 5px 0px;
}
.row{
width: 100%;
}
.col4{
display: inline-block;
margin: 4px 3px;
width: 30%;
}
}
.tagactive{
background: #3471FF !important;
color: #fff !important;
}
</style>
+66 -20
View File
@@ -99,24 +99,34 @@
<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="flex" v-if="item.type==0">
<view class="">
<view class="">
<view class="lingh">
{{$t('times')}} :{{item.created_at}}
</view>
<view class="">{{$t('address')}}:{{item.address}}</view>
<view class="">{{$t('customer.Visitcontent')}}:{{item.audio_text}}</view>
<view class="lingh">{{$t('customer.Visitcontent')}}:{{item.audio_text}}</view>
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
<!-- <image :src="item.oss_picture" mode=""></image> -->
<u-album
:urls="isurls(item.oss_picture)"
:singleSize="80"
keyName="src"
></u-album>
</view>
</view>
<view class="" v-else>
<view class="">
<view class="lingh">
{{$t('times')}}:{{item.created_at}}
</view>
<view class="">
<image :src="item.oss_picture" mode=""></image>
<!-- <image :src="item.oss_picture" mode=""></image> -->
<u-album
:urls="isurls(item.oss_picture)"
:singleSize="80"
keyName="src"
></u-album>
</view>
</view>
</view>
@@ -200,6 +210,13 @@
leftClick(){
uni.navigateBack({})
},
isurls(url){
var urls=[]
var obj={}
obj.src = url
urls.push(obj)
return urls
},
close(val){
this[val]=false
},
@@ -282,6 +299,25 @@
},
});
},
unigetLocation(){
var that = this
uni.getLocation({
type: 'wgs84', // 默认为 wgs84 坐标系,可选 gcj02
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
that.getarrd(res.longitude,res.latitude)
// 如果需要将经纬度转换为具体地址,可以使用逆地理编码
// 这里调用 uni.chooseLocation 或第三方地图服务(如高德、腾讯地图)
},
fail: function (err) {
console.log('获取位置失败:', err);
},
complete: function () {
console.log('获取位置完成');
}
});
},
getlocahost() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
@@ -293,11 +329,12 @@
console.log("获取位置成功:", position);
},
(error) => {
this.error = this.getErrorMessage(error);
uni.showToast({
title: this.error,
icon: 'none'
});
this.unigetLocation()
// this.error = this.getErrorMessage(error);
// uni.showToast({
// title: this.error,
// icon: 'none'
// });
console.error("获取位置失败:", error);
},
{
@@ -307,11 +344,12 @@
}
);
} else {
this.error = "浏览器不支持 Geolocation API";
uni.showToast({
title: this.error,
icon: 'none'
});
this.unigetLocation()
// this.error = "浏览器不支持 Geolocation API";
// uni.showToast({
// title: this.error,
// icon: 'none'
// });
console.error("浏览器不支持 Geolocation API");
}
},
@@ -427,14 +465,14 @@
header:{'Authorization': 'Bearer ' + uni.getStorageSync('token')},
success: (uploadFileRes) => {
const path=JSON.parse(uploadFileRes.data)
if(path.code==-1){
if(path.code==0){
that.form[name] = path.data.path
console.log(that.form)
}else{
uni.showToast({
title: path.message,
icon: 'none'
});
}else{
that.form[name] = path.data.path
console.log(that.form)
}
}
});
@@ -722,6 +760,14 @@
justify-content: space-between;
align-items: center;
color: #999999;
.lingh{
line-height: 40px;
}
.flex{
display: flex;
justify-content: space-between;
align-items: center;
}
}
.title{
color: #666666;
+31 -10
View File
@@ -153,6 +153,25 @@ export default {
});
});
},
unigetLocation(){
var that = this
uni.getLocation({
type: 'wgs84', // 默认为 wgs84 坐标系,可选 gcj02
success: function (res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
that.addmapmarkfn(res.latitude,res.longitude)
// 如果需要将经纬度转换为具体地址,可以使用逆地理编码
// 这里调用 uni.chooseLocation 或第三方地图服务(如高德、腾讯地图)
},
fail: function (err) {
console.log('获取位置失败:', err);
},
complete: function () {
console.log('获取位置完成');
}
});
},
initMap() {
var that = this
loader
@@ -171,11 +190,12 @@ export default {
console.log("获取位置成功:", position);
},
(error) => {
this.error = this.getErrorMessage(error);
uni.showToast({
title: this.error,
icon: 'none'
});
that.unigetLocation()
// this.error = this.getErrorMessage(error);
// uni.showToast({
// title: this.error,
// icon: 'none'
// });
console.error("获取位置失败:", error);
},
{
@@ -185,11 +205,12 @@ export default {
}
);
} else {
this.error = "浏览器不支持 Geolocation API";
uni.showToast({
title: this.error,
icon: 'none'
});
that.unigetLocation()
// this.error = "浏览器不支持 Geolocation API";
// uni.showToast({
// title: this.error,
// icon: 'none'
// });
console.error("浏览器不支持 Geolocation API");
}
}
+6 -9
View File
@@ -172,7 +172,6 @@
created:this.timevalue
}
}).then(res => {
console.log(res.data.data)
this.statisticsdata = res.data.data
})
},
@@ -204,21 +203,20 @@
this.columnstime =[
[{
label: this.$t('all'),
id: '0'
id: ''
},{
label: this.$t('onedayn'),
id: '1'
id: '0'
}, {
label: this.$t('threedayn'),
id: '3'
id: '1'
}, {
label: this.$t('sevendayn'),
id: '7'
id: '2'
}]
];
this.columnstime[0].forEach((item,index) => {
if(item.id == that.filter){
console.log(item.label)
that.secelttime = item.label
}
})
@@ -291,7 +289,6 @@
filter:this.filter
}
}).then(res => {
console.log(res.data)
if(res.data.code ==0){
var datas = res.data.data.list;
this.$refs.paging.complete(datas);
@@ -444,7 +441,7 @@
}
}
.gjtimetop{
margin:5px 15px;
margin:20px 15px 0px;
display: flex;
align-items: center;
justify-content: space-between;
@@ -463,7 +460,7 @@
}
}
.gjtime{
padding: 15px;
padding:5px 15px 15px;
}
.contents{
+24 -8
View File
@@ -8,26 +8,26 @@
<view class="left">
<view class="title">
<view class="leftbg"></view>
<view>刘亦菲</view>
<view>{{userinfo.name}}</view>
</view>
<view class="ftitle">业务经理</view>
<view class="ftitle">{{userinfo.position}}</view>
</view>
<view>
<image src="/static/image/mine/user.png" mode=""></image>
<image :src="userinfo.avatar" mode=""></image>
</view>
</view>
<view class="conts">
<view class="coles">
<image src="/static/image/mine/phone.png" mode=""></image>
<view class="">13838225452</view>
<view class="">{{userinfo.mobile}}</view>
</view>
<view class="coles">
<image src="/static/image/mine/email.png" style="height:13px;" mode=""></image>
<view class="">17752584152@163.com</view>
<view class="">{{userinfo.email}}</view>
</view>
<view class="coles">
<image src="/static/image/mine/addr.png" style="height:18px;width: 14px;" mode=""></image>
<view class="">13838225452</view>
<view class="">{{userinfo.country_name}}</view>
</view>
</view>
<view class="code">
@@ -52,10 +52,25 @@
export default {
data() {
return {
userinfo:{}
}
},
onLoad() {
this.getinfo()
},
methods: {
leftClick(){
uni.navigateBack({})
},
getinfo(){
var that= this;
request({
url:'user/getInfo',
method:'get',
}).then(res => {
that.userinfo = res.data.data;
})
},
saveImgFile(baseImg){
const bitmap = new plus.nativeObj.Bitmap('test')
bitmap.loadBase64Data(
@@ -180,6 +195,7 @@
image{
width: 100px;
height: 100px;
border-radius: 50%;
}
}
.conts{
@@ -201,7 +217,7 @@
background-color: rgba(255,255,255,50%);
border-radius: 10px;
text-align: center;
width: 50%;
width: 340rpx;
margin: auto;
padding: 15px;
image{
+3
View File
@@ -26,6 +26,9 @@
}
},
methods: {
leftClick(){
uni.navigateBack({})
},
//客户列表数据
queryList(pageNo, pageSize) {
var that = this;
Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B