init
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
<!-- 话数库 -->
|
||||
<template>
|
||||
<div class="scriptLibary_container" :style="{ 'max-height': maxHeight, height: height }">
|
||||
<div class="script_list">
|
||||
<scroll-view scroll-y="true" class="script_list_scroll">
|
||||
<div class="add_script" v-if="speechArtType == 1" @click="addSpeech">
|
||||
<div><span class="iconfont"></span></div>
|
||||
<div><span>添加自动回复</span></div>
|
||||
</div>
|
||||
<div class="script_list_item" v-for="(item, index) in authReply" :key="index" @click="selectScript(item)">
|
||||
<div class="script_list_item_label">{{ item.keyword }}</div>
|
||||
<div class="script_list_item_value">{{ item.content }}</div>
|
||||
<div class="edit_box" v-if="speechArtType == 1">
|
||||
<div @click.stop="editSpeech(item)"><span class="iconfont"></span></div>
|
||||
<div @click.stop="handleDeleteServiceSpeechcraft(item)"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</div>
|
||||
|
||||
<uni-popup ref="addEdGroup" animation type="center">
|
||||
<div class="addGroup_container">
|
||||
<div class="addGroup_container_title">
|
||||
<div></div>
|
||||
<div v-if="speechData.id">编辑自动回复</div>
|
||||
<div v-else>添加自动回复</div>
|
||||
<div @click="closeAddGroup"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="addGroup_form">
|
||||
<div class="input_box"><input v-model="speechData.keyword" type="text" placeholder="请输入关键词,多个关键字请用逗号隔开" /></div>
|
||||
<div class="input_box"><textarea v-model="speechData.content" type="text" placeholder="请输入自动回复内容"></textarea></div>
|
||||
<div class="input_box" style='width: 40%;'><input v-model="speechData.sort" type="number" placeholder='排序' /></div>
|
||||
<div class="button_box" :class="{ canInput: speechData.keyword && speechData.content }" @click="handleSubmiteditAdd"><div>确定</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Toast, throttle, serialize, Modal, ActionSheet } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
props: {
|
||||
// 话术库分类
|
||||
speechArtType: {
|
||||
type: Number | String,
|
||||
default: '1'
|
||||
},
|
||||
// 话术检索
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否展示添加话术
|
||||
icCanEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
authReply: [],
|
||||
where: {
|
||||
page: 1,
|
||||
limit: 5
|
||||
},
|
||||
scriptList: [],
|
||||
pageData: {
|
||||
page: 1,
|
||||
limit: '200'
|
||||
},
|
||||
cateId: '', // 选中的侧边栏ID
|
||||
speechData: {
|
||||
keyword: '',
|
||||
content: '',
|
||||
sort:0
|
||||
},
|
||||
userGroupData: {
|
||||
name: '',
|
||||
sort: ''
|
||||
},
|
||||
handleAdEdType: 1, // 1新增 2修改
|
||||
handleGroupTitle: '新增分组',
|
||||
groupType: 1 // 1新增 2修改
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
authReply: {
|
||||
handler(val) {
|
||||
console.log(val);
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
title: {
|
||||
handler(val) {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getAuthReplyList();
|
||||
},
|
||||
methods: {
|
||||
// 查询话术类
|
||||
getAuthReplyList() {
|
||||
http(api.getAuthReply, this.where).then(res => {
|
||||
this.authReply = res;
|
||||
});
|
||||
},
|
||||
// 添加话术
|
||||
addSpeech() {
|
||||
this.handleAdEdType = 1;
|
||||
this.speechData = {};
|
||||
this.$refs.addEdGroup.open();
|
||||
},
|
||||
// 修改自动回复
|
||||
editSpeech(item) {
|
||||
this.handleAdEdType = 2;
|
||||
this.speechData = serialize(item);
|
||||
this.$refs.addEdGroup.open();
|
||||
},
|
||||
// 确认新增,修改自动回复
|
||||
handleSubmiteditAdd() {
|
||||
this.speechData.id = this.speechData.id ? this.speechData.id : 0;
|
||||
http(api.saveAuthReply, this.speechData).then(res => {
|
||||
Toast(this.speechData.id ? '修改成功' : '添加成功');
|
||||
this.getAuthReplyList();
|
||||
this.closeAddGroup();
|
||||
});
|
||||
},
|
||||
// 删除自动回复
|
||||
handleDeleteServiceSpeechcraft(item) {
|
||||
Modal('温馨提示', `自动回复"${item.content}"将被删除,请问是否继续?`).then(res => {
|
||||
http(api.deleteAuthReply,item).then(res => {
|
||||
Toast('删除成功');
|
||||
this.getAuthReplyList();
|
||||
});
|
||||
});
|
||||
},
|
||||
closeAddGroup() {
|
||||
this.$refs.addEdGroup.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.scriptLibary_container {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
.script_group {
|
||||
width: 176rpx;
|
||||
background: #f5f6f9;
|
||||
.script_group_scroll {
|
||||
height: 100%;
|
||||
.tag_list {
|
||||
width: 100%;
|
||||
height: 109rpx;
|
||||
.iconfont {
|
||||
color: #9f9f9f;
|
||||
font-size: 11px;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
.title_value {
|
||||
color: #9f9f9f;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
top: 2rpx;
|
||||
}
|
||||
.tag_list_tag {
|
||||
width: 6rpx;
|
||||
height: 46rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag_list_group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
|
||||
.tag_list_label {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
white-space: nowrap;
|
||||
color: #282828;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.script_list {
|
||||
flex: 1;
|
||||
.add_script {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 30rpx;
|
||||
height: 109rpx;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.script_list_scroll {
|
||||
height: 100%;
|
||||
.script_list_item {
|
||||
padding: 25rpx 30rpx;
|
||||
background-color: #ffffff;
|
||||
&_label {
|
||||
color: #282828;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
&_value {
|
||||
font-size: 14px;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
}
|
||||
.edit_box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
> div {
|
||||
margin-left: 48rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.selectEdTag {
|
||||
background: #fff !important;
|
||||
.tag_list_label {
|
||||
color: @primaryColor !important;
|
||||
}
|
||||
}
|
||||
|
||||
.addGroup_container {
|
||||
width: 690rpx;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
&_title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding: 30rpx 30rpx 50rpx 0;
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c8cad0;
|
||||
}
|
||||
> div {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
> div:nth-child(3) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.addGroup_form {
|
||||
padding: 0 30rpx;
|
||||
padding-bottom: 69rpx;
|
||||
.input_box {
|
||||
margin-bottom: 32rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 14rpx;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
input {
|
||||
font-size: 14px;
|
||||
height: 68rpx;
|
||||
}
|
||||
textarea {
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
height: 192rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.button_box {
|
||||
margin-top: 60rpx;
|
||||
> div {
|
||||
height: 86rpx;
|
||||
background: #c8cad0;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.canInput {
|
||||
> div {
|
||||
height: 86rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,159 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<!-- <div slot="header" class="header"><div class="header_title">自动回复</div></div> -->
|
||||
<div slot="content" class="content">
|
||||
<div class="caption">
|
||||
<div class="">自动回复开关:</div>
|
||||
<div class="right"><switch @change="changeSwitch" :checked="authReply" /></div>
|
||||
</div>
|
||||
|
||||
<div class="scriptLibary_content">
|
||||
<scripts-libary :speechArtType="speechArtType" :maxHeight="maxHeight" icCanEdit :tagList="speechTagList" :title="propstitle"></scripts-libary>
|
||||
</div>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scriptsLibary from './component/scriptLibary.vue';
|
||||
import { navigateTo, navigateBack } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: {
|
||||
scriptsLibary
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
authReply: false,
|
||||
maxHeight: '',
|
||||
speechArtType: '',
|
||||
speechArtTypeConcat: {
|
||||
1: '个人库',
|
||||
0: '公共库'
|
||||
},
|
||||
speechTagList: [], // 话术分类
|
||||
propstitle: ''
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.speechArtType = opt.speechArtType;
|
||||
this.selectScriptLibary();
|
||||
console.log(this.speechArtType);
|
||||
this.$nextTick(() => {
|
||||
let info = uni.createSelectorQuery().select('.content');
|
||||
info.boundingClientRect(data => {
|
||||
this.maxHeight = Math.ceil(data.height) * 1.85 + 'rpx';
|
||||
}).exec();
|
||||
});
|
||||
this.getKefuInfo();
|
||||
},
|
||||
methods: {
|
||||
getKefuInfo() {
|
||||
this.$store.dispatch('getKeufuInfo').then(res => {
|
||||
this.authReply = !!res.auto_reply;
|
||||
});
|
||||
},
|
||||
changeSwitch(e) {
|
||||
console.log(e);
|
||||
http(api.putAuthReply, {
|
||||
value: e.detail.value ? 1 : 0
|
||||
}).then(res => {
|
||||
this.speechTagList = res.data;
|
||||
});
|
||||
},
|
||||
// 查询话术类
|
||||
selectScriptLibary() {
|
||||
http(api.kefuServiceCate, {
|
||||
type: this.speechArtType
|
||||
}).then(res => {
|
||||
this.speechTagList = res.data;
|
||||
});
|
||||
},
|
||||
finish() {
|
||||
navigateBack(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.header {
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 30rpx;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
&_title {
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: @primaryColor;
|
||||
}
|
||||
}
|
||||
.scriptLibary_search {
|
||||
background: #fff;
|
||||
padding-bottom: 44rpx;
|
||||
border-bottom: 1px solid #f0f3fa;
|
||||
> div {
|
||||
display: flex;
|
||||
background: #f5f6f9;
|
||||
width: 690rpx;
|
||||
height: 68rpx;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 39px;
|
||||
> input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
.scriptLibary_content {
|
||||
}
|
||||
.caption {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 25rpx 30rpx;
|
||||
div:first-of-type {
|
||||
margin-left: 5px;
|
||||
}
|
||||
div {
|
||||
width: 50%;
|
||||
}
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
/deep/ .uni-switch-input {
|
||||
height: 24px;
|
||||
}
|
||||
/deep/ .uni-switch-input:after,
|
||||
/deep/ .uni-switch-input:before {
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="auth_login container">
|
||||
<div class="auth_login_content">
|
||||
<div class="userData">
|
||||
<div class="avater"><image :src="userData.avatar" mode=""></image></div>
|
||||
<div class="userName">
|
||||
<span>{{ userData.nickname }}</span>
|
||||
</div>
|
||||
<div class="tipMessage">点击授权登录您的客服工作台</div>
|
||||
</div>
|
||||
|
||||
<div class="handle">
|
||||
<div class="handle_login" @click="handle_login">授权登录</div>
|
||||
<div class="handle_cancel" @click="handleCancel">取消</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import { navigateTo, Modal, navigateBack } from 'pages/utils/uniApi.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
key: '',
|
||||
userData: {}
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.key = opt.key;
|
||||
this.userData = this.$store.state.kefuInfo;
|
||||
},
|
||||
|
||||
methods: {
|
||||
handle_login() {
|
||||
http(api.serviceCode, { code: this.key }).then(res => {
|
||||
Modal('温馨提示', '登录成功', { showCancel: false }).then(() => {
|
||||
navigateBack(1);
|
||||
});
|
||||
});
|
||||
},
|
||||
handleCancel() {
|
||||
navigateBack(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.auth_login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
&_content {
|
||||
flex: 1;
|
||||
.userData {
|
||||
.avater {
|
||||
width: 178rpx;
|
||||
height: 178rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin: 112rpx auto 20rpx auto;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.userName {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.tipMessage {
|
||||
text-align: center;
|
||||
color: #9F9F9F;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.handle {
|
||||
margin-top: 96rpx;
|
||||
> div {
|
||||
width: 594rpx;
|
||||
height: 86rpx;
|
||||
border-radius: 43rpx;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
&_login {
|
||||
background: linear-gradient(90deg, #3875ea 0%, #1890fc 100%);
|
||||
color: #fff;
|
||||
}
|
||||
&_cancel {
|
||||
margin-top: 28rpx !important;
|
||||
border: 1px solid #3875EA;
|
||||
color: #3875EA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="header_banner">
|
||||
<div class="header_banner_content">
|
||||
<div class="header_banner_content_title"><span>提建议或举报不良内容</span></div>
|
||||
<div class="header_banner_content_message">
|
||||
<span>亲,若您收到不良信息,请及时反馈,我们非常重视您给我们提出宝贵的建议,帮助我们不断完善产品,谢谢!</span></div>
|
||||
</div>
|
||||
<div class="header_banner_image">
|
||||
<div class="header_banner_image_imageBox">
|
||||
<image src="~static/image/feedback/bg.png" mode="widthFix"></image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="organization_work">
|
||||
|
||||
<div class="organization_work_item">
|
||||
<div class="organization_work_item_label">
|
||||
<span>09:00~22:00</span>
|
||||
</div>
|
||||
<div class="organization_work_item_value">
|
||||
<span>我们的工作时间</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip"></div>
|
||||
<div class="organization_work_item">
|
||||
<div class="organization_work_item_label">
|
||||
<span>400-8888-794</span>
|
||||
</div>
|
||||
<div class="organization_work_item_value">
|
||||
<span>售前客服电话</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> -->
|
||||
|
||||
<div class="feedback">
|
||||
<div class="feedback_title"><span>我要投诉</span></div>
|
||||
|
||||
<div class="feedback_list">
|
||||
<div class="feedback_list_item" v-for="(item, index) in feedbackList" :key="index"
|
||||
@click="selectItem(item)">
|
||||
<div>
|
||||
<div :class="{ feedback_list_item_selected: item.selected }"></div>
|
||||
</div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="feedback_input">
|
||||
<input v-model="feedBackData.rela_name" type="text" value="" placeholder="请输入您的姓名"/>
|
||||
</div>
|
||||
<div class="feedback_input">
|
||||
<input v-model="feedBackData.phone" type="text" value="" placeholder="请输入您的联系电话" />
|
||||
</div> -->
|
||||
|
||||
<div class="feedback_textarea"><textarea v-model="feedBackData.content" value="" placeholder="请填写留言内容" />
|
||||
</div>
|
||||
|
||||
<div class="handle_button" @click="handleSubmit"><span>提交</span></div>
|
||||
</div>
|
||||
|
||||
<uni-popup ref="feedbackReslove" animation>
|
||||
<submit-response @handleSubmitRes="handleSubmitRes"></submit-response>
|
||||
</uni-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
navigateBack
|
||||
} from 'pages/utils/uniApi.js';
|
||||
import submitResponse from '../feedback/component/submitResponse.vue';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: {
|
||||
submitResponse
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
feedBackData: {
|
||||
content: '',
|
||||
user_id: '',
|
||||
cate_id: []
|
||||
},
|
||||
feedbackList: [],
|
||||
userId: 0,
|
||||
};
|
||||
},
|
||||
onLoad(option) {
|
||||
this.userId = option.id || 0;
|
||||
},
|
||||
onShow() {
|
||||
this.getUserComplain();
|
||||
},
|
||||
methods: {
|
||||
// 获取投诉内容列表
|
||||
getUserComplain() {
|
||||
http(api.userComplain).then(res => {
|
||||
this.feedbackList = res;
|
||||
this.feedbackList.forEach(item => {
|
||||
this.$set(item, 'selected', false);
|
||||
});
|
||||
});
|
||||
},
|
||||
// 选择投诉项目
|
||||
selectItem(item) {
|
||||
item.selected = !item.selected;
|
||||
},
|
||||
handleSubmit() {
|
||||
this.feedBackData.cate_id = this.feedbackList.filter(item => item.selected).map(val => val.id);
|
||||
this.feedBackData.user_id = this.userId;
|
||||
|
||||
http(api.postUserComplain, this.feedBackData).then(res => {
|
||||
this.$refs.feedbackReslove.open('center');
|
||||
});
|
||||
},
|
||||
handleSubmitRes() {
|
||||
navigateBack(1);
|
||||
this.$refs.feedbackReslove.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('../feedback/less/feedback.less');
|
||||
</style>
|
||||
@@ -0,0 +1,536 @@
|
||||
<!-- 话数库 -->
|
||||
<template>
|
||||
<div class="scriptLibary_container" :style="{ 'max-height': maxHeight, height: height,'min-height': minWidth, width: width }">
|
||||
<div class="script_group">
|
||||
<scroll-view scroll-y="true" class="script_group_scroll">
|
||||
<div class="tag_list flex-center" @click="addGroup" v-if="speechArtType == 1">
|
||||
<span class="iconfont"></span>
|
||||
<span class="title_value">分组</span>
|
||||
</div>
|
||||
<div class="tag_list tag_list_group" v-for="(item, index) in tagList" :key="index" :class="{ selectEdTag: cateId == item.id }" @click="selectTags(item)">
|
||||
<div class="tag_list_tag" v-if="cateId == item.id"></div>
|
||||
<div class="tag_list_label">{{ item.name }}</div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</div>
|
||||
<div class="script_list">
|
||||
<scroll-view scroll-y="true" class="script_list_scroll">
|
||||
<div class="add_script" v-if="speechArtType == 1" @click="addSpeech">
|
||||
<div><span class="iconfont"></span></div>
|
||||
<div><span>添加话术</span></div>
|
||||
</div>
|
||||
<div class="script_list_item" v-for="(item, index) in scriptList" :key="index" @click="selectScript(item)">
|
||||
<div class="script_list_item_label">{{ item.title }}</div>
|
||||
<div class="script_list_item_value line2">{{ item.message }}</div>
|
||||
<div class="edit_box" v-if="speechArtType == 1">
|
||||
<div @click.stop="editSpeech(item)"><span class="iconfont"></span></div>
|
||||
<div @click.stop="handleDeleteServiceSpeechcraft(item)"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</div>
|
||||
|
||||
<uni-popup ref="addEdGroup" animation type="center">
|
||||
<div class="addGroup_container">
|
||||
<div class="addGroup_container_title">
|
||||
<div></div>
|
||||
<div>添加话术</div>
|
||||
<div @click="closeAddGroup"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="addGroup_form">
|
||||
<div class="input_box"><input class="inp_title" maxlength="20" v-model="speechData.title" type="text" placeholder="请输入标题名称" /></div>
|
||||
<div class="input_box"><textarea v-model="speechData.message" type="text" placeholder="请输入您的话术"></textarea></div>
|
||||
<div class="button_box" :class="{ canInput: speechData.title && speechData.message }" @click="handleSubmiteditAdd"><div>确定</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="addEdUserGroups" animation type="center">
|
||||
<div class="addGroup_container">
|
||||
<div class="addGroup_container_title">
|
||||
<div></div>
|
||||
<div>{{handleGroupTitle}}</div>
|
||||
<div @click="closeUserGroups"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="addGroup_form">
|
||||
<div class="input_box"><input v-model.trim="userGroupData.name" maxlength="4" type="text" placeholder="请输入分组名称" /></div>
|
||||
<div class="input_box"><input v-model="userGroupData.sort" type="text" placeholder="请输入分组排序"></input></div>
|
||||
<div class="button_box" :class="{ canInput: userGroupData.name }" @click="handleSubmitUserGroup"><div>确定</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Toast, throttle, serialize, Modal, ActionSheet } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
props: {
|
||||
// 话术库分类
|
||||
speechArtType: {
|
||||
type: Number | String,
|
||||
default: '1'
|
||||
},
|
||||
// 话术检索
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否展示添加话术
|
||||
icCanEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
minWidth: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 话术分类
|
||||
tagList: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
scriptList: [],
|
||||
pageData: {
|
||||
page: 1,
|
||||
limit: '200'
|
||||
},
|
||||
cateId: '', // 选中的侧边栏ID
|
||||
speechData: {
|
||||
title: '',
|
||||
message: ''
|
||||
},
|
||||
userGroupData: {
|
||||
name: '',
|
||||
sort: ''
|
||||
},
|
||||
handleAdEdType: 1, // 1新增 2修改
|
||||
handleGroupTitle: '新增分组',
|
||||
groupType: 1, // 1新增 2修改
|
||||
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
speechArtType: {
|
||||
handler(val) {
|
||||
this.selectScriptLibary();
|
||||
// this.getSpeechArtList('init');
|
||||
console.log(this.tagList);
|
||||
}
|
||||
},
|
||||
title: {
|
||||
handler(val) {
|
||||
setTimeout(() => {
|
||||
this.getSpeechArtList();
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
tagList: {
|
||||
handler(val) {
|
||||
this.getSpeechArtList('init');
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.selectScriptLibary();
|
||||
},
|
||||
methods: {
|
||||
// 查询话术类
|
||||
selectScriptLibary() {
|
||||
http(api.kefuServiceCate, {
|
||||
type: this.speechArtType
|
||||
}).then(res => {
|
||||
this.tagList = res.data;
|
||||
this.getSpeechArtList('init');
|
||||
});
|
||||
},
|
||||
// 获取话术列表
|
||||
getSpeechArtList(type = 'select') {
|
||||
if (this.tagList.length) {
|
||||
if (type == 'init') {
|
||||
this.cateId = this.tagList[0].id;
|
||||
}
|
||||
http(api.serviceSpeechcraft, {
|
||||
cate_id: this.cateId,
|
||||
type: this.speechArtType,
|
||||
...this.pageData,
|
||||
title: this.title
|
||||
}).then(res => {
|
||||
this.scriptList = res;
|
||||
this.speechData = {
|
||||
title: '',
|
||||
message: ''
|
||||
}
|
||||
console.log(this.scriptList);
|
||||
});
|
||||
} else {
|
||||
// setTimeout(() => {
|
||||
// this.getSpeechArtList(type);
|
||||
// }, 500);
|
||||
}
|
||||
},
|
||||
// 选择标签
|
||||
selectTags(item) {
|
||||
if(this.cateId == item.id) {
|
||||
console.log(item);
|
||||
this.userGroupData = serialize(item);
|
||||
ActionSheet(['编辑', '删除']).then(res => {
|
||||
console.log(res)
|
||||
switch(res) {
|
||||
case 0:
|
||||
this.groupType = 2;
|
||||
this.handleGroupTitle = '编辑分组';
|
||||
this.$refs.addEdUserGroups.open();
|
||||
break;
|
||||
case 1:
|
||||
Modal('温馨提示', `分组 "${item.name}"将被删除, 请问是否继续?`).then(() => {
|
||||
http(api.deleteServiceCate, item).then(res => {
|
||||
Toast('删除成功');
|
||||
this.selectScriptLibary('init');
|
||||
})
|
||||
})
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.cateId = item.id;
|
||||
this.getSpeechArtList();
|
||||
}
|
||||
},
|
||||
// 选择话术
|
||||
selectScript(item) {
|
||||
this.$emit('sendSpeechMessage', item);
|
||||
},
|
||||
// 添加话术
|
||||
addSpeech() {
|
||||
this.speechData.title = '';
|
||||
this.speechData.message = '';
|
||||
this.handleAdEdType = 1;
|
||||
this.$refs.addEdGroup.open();
|
||||
},
|
||||
// 修改话术
|
||||
editSpeech(item) {
|
||||
this.handleAdEdType = 2;
|
||||
this.speechData = serialize(item);
|
||||
this.$refs.addEdGroup.open();
|
||||
},
|
||||
// 确认新增,修改话术
|
||||
handleSubmiteditAdd() {
|
||||
if (this.handleAdEdType == 1) {
|
||||
this.addSpeechClass();
|
||||
return;
|
||||
}
|
||||
if ((this.handleAdEdType = 2)) {
|
||||
this.editSpeechClass();
|
||||
return;
|
||||
}
|
||||
},
|
||||
// 修改话术事件
|
||||
editSpeechClass() {
|
||||
let canInput = true;
|
||||
console.log(this.speechData);
|
||||
|
||||
Object.keys(this.speechData).forEach(item => {
|
||||
if (!this.speechData.title || !this.speechData.message) {
|
||||
canInput = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!canInput) {
|
||||
Toast('请将内容填写完整');
|
||||
return;
|
||||
}
|
||||
|
||||
http(api.putServiceSpeechcraft, this.speechData).then(res => {
|
||||
Toast('修改成功');
|
||||
this.getSpeechArtList();
|
||||
this.$refs.addEdGroup.close();
|
||||
});
|
||||
},
|
||||
// 新增话术事件
|
||||
addSpeechClass() {
|
||||
let canInput = true;
|
||||
|
||||
Object.keys(this.speechData).forEach(item => {
|
||||
if (!this.speechData[item]) {
|
||||
canInput = false;
|
||||
}
|
||||
});
|
||||
if (!canInput) {
|
||||
Toast('请将内容填写完整');
|
||||
return;
|
||||
}
|
||||
http(api.postServiceSpeechcraft, {
|
||||
...this.speechData,
|
||||
cate_id: this.cateId
|
||||
}).then(res => {
|
||||
Toast('新增成功');
|
||||
this.getSpeechArtList();
|
||||
this.$refs.addEdGroup.close();
|
||||
});
|
||||
},
|
||||
// 删除话术
|
||||
handleDeleteServiceSpeechcraft(item) {
|
||||
Modal('温馨提示', `话术"${item.title}"将被删除,请问是否继续?`).then(res => {
|
||||
http(api.deleteServiceSpeechcraft, item).then(res => {
|
||||
Toast('删除成功');
|
||||
this.getSpeechArtList();
|
||||
});
|
||||
});
|
||||
},
|
||||
closeAddGroup() {
|
||||
this.$refs.addEdGroup.close();
|
||||
},
|
||||
// 新增分组
|
||||
addGroup() {
|
||||
this.groupType = 1;
|
||||
this.$refs.addEdUserGroups.open();
|
||||
},
|
||||
// 确定新增 或 修改 分组 1增 2改
|
||||
async handleSubmitUserGroup() {
|
||||
if(this.groupType == 1) {
|
||||
await http(api.serviceCate, {
|
||||
...this.userGroupData
|
||||
}).then(res => {
|
||||
Toast('添加成功');
|
||||
})
|
||||
}
|
||||
|
||||
if(this.groupType == 2) {
|
||||
console.log(this.userGroupData);
|
||||
await http(api.putServiceCate, this.userGroupData).then(res => {
|
||||
Toast('修改成功');
|
||||
this.selectScriptLibary();
|
||||
this.$refs.addEdUserGroups.close();
|
||||
})
|
||||
}
|
||||
|
||||
this.selectScriptLibary();
|
||||
this.$refs.addEdUserGroups.close();
|
||||
this.userGroupData = {
|
||||
name: '',
|
||||
sort: ''
|
||||
}
|
||||
},
|
||||
// 关闭分组弹框
|
||||
closeUserGroups() {
|
||||
this.$refs.addEdUserGroups.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.scriptLibary_container {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
.script_group {
|
||||
// width: 176rpx;
|
||||
width: 20%;
|
||||
position: fixed;
|
||||
background: #f5f6f9;
|
||||
.script_group_scroll {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.tag_list {
|
||||
width: 100%;
|
||||
height: 109rpx;
|
||||
.iconfont {
|
||||
color: #9f9f9f;
|
||||
font-size: 11px;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
.title_value {
|
||||
color: #9f9f9f;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
top: 2rpx;
|
||||
}
|
||||
.tag_list_tag {
|
||||
width: 6rpx;
|
||||
height: 46rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.flex-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.tag_list_group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
position: relative;
|
||||
|
||||
.tag_list_label {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
white-space: nowrap;
|
||||
color: #282828;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.script_list {
|
||||
// flex: 1;
|
||||
width: 80%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
.add_script {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 30rpx;
|
||||
height: 109rpx;
|
||||
}
|
||||
.script_list_scroll {
|
||||
height: 100%;
|
||||
.script_list_item {
|
||||
padding: 25rpx 30rpx;
|
||||
&_label {
|
||||
color: #282828;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
&_value {
|
||||
font-size: 14px;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
}
|
||||
.edit_box {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
> div {
|
||||
margin-left: 48rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.selectEdTag {
|
||||
background: #fff !important;
|
||||
.tag_list_label {
|
||||
color: @primaryColor !important;
|
||||
}
|
||||
}
|
||||
|
||||
.addGroup_container {
|
||||
width: 690rpx;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
&_title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding: 30rpx 30rpx 50rpx 0;
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c8cad0;
|
||||
}
|
||||
> div {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
> div:nth-child(3) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.addGroup_form {
|
||||
padding: 0 30rpx;
|
||||
padding-bottom: 69rpx;
|
||||
.input_box {
|
||||
margin-bottom: 32rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 14rpx;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
input {
|
||||
font-size: 14px;
|
||||
height: 68rpx;
|
||||
}
|
||||
textarea {
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
height: 192rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.button_box {
|
||||
margin-top: 60rpx;
|
||||
> div {
|
||||
height: 86rpx;
|
||||
background: #c8cad0;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.canInput {
|
||||
> div {
|
||||
height: 86rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.line2 {
|
||||
display: -webkit-box;
|
||||
overflow: hidden;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
.inp_title {
|
||||
width: 600rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<div class="transfer_container">
|
||||
<div class="transfer_container_title">
|
||||
<div class="transfer_container_title_value"><span>转接客服</span></div>
|
||||
<div class="transfer_container_title_icon" @click="close"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="customerServer_list">
|
||||
<scroll-view scroll-y="true" class="max_height">
|
||||
<div class="customerServer_list_item" v-for="(item, index) in serverList" :key="index" @click="selectCustomerServer(item)">
|
||||
<div class="customerServer_list_item_radio">
|
||||
<div><div v-if="item.select"></div></div>
|
||||
</div>
|
||||
<div class="customerServer_list_item_avar"><image :src="item.avatar" mode=""></image></div>
|
||||
<div class="customerServer_list_item_nickName">
|
||||
<span>{{ item.nickname }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
</div>
|
||||
|
||||
<div class="handle_box" @click="handleSubmit"><div>确定</div></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Toast } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
props:{
|
||||
userInfo:{
|
||||
type:Object,
|
||||
default:{}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
serverList: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods: {
|
||||
// 查询其他客服
|
||||
initData() {
|
||||
http(api.serviceTransferList).then(res => {
|
||||
this.serverList = res.list;
|
||||
this.serverList.forEach(item => {
|
||||
this.$set(item, 'select', false);
|
||||
});
|
||||
console.log(this.serverList);
|
||||
});
|
||||
},
|
||||
// 选择客服
|
||||
selectCustomerServer(item) {
|
||||
if (item.select) {
|
||||
item.select = false;
|
||||
} else {
|
||||
this.serverList.forEach(item => {
|
||||
item.select = false;
|
||||
});
|
||||
item.select = true;
|
||||
}
|
||||
},
|
||||
// 确认转接
|
||||
handleSubmit() {
|
||||
http(api.serviceTransfer, {
|
||||
kefuToUserId: this.serverList.find(item => item.select).user_id, // 转接人id
|
||||
user_id: this.userInfo.id
|
||||
}).then(res => {
|
||||
Toast('转接成功');
|
||||
this.$emit('handleSubmit');
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.transfer_container {
|
||||
padding: 40rpx 0 68rpx 0;
|
||||
background: #fff;
|
||||
border-radius: 12rpx 12rpx 0px 0px;
|
||||
&_title {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 0 30rpx;
|
||||
&_value {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #282828;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
}
|
||||
&_icon {
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c8cad0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.customerServer_list {
|
||||
&_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 30px;
|
||||
height: 122rpx;
|
||||
border-bottom: 1px solid #f0f2f7;
|
||||
&_radio {
|
||||
margin-right: 38rpx;
|
||||
> div {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border: 1px solid @primaryColor;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> div {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
background: @primaryColor;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
&_avar {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
margin-right: 28rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
&_nickName {
|
||||
color: #282828;
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.handle_box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 80rpx;
|
||||
> div {
|
||||
width: 690rpx;
|
||||
height: 86rpx;
|
||||
background: #3875ea;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
color: #ffffff;
|
||||
font-size: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.max_height {
|
||||
max-height: 772rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,336 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out titleName="客户信息" headerColor="#fff">
|
||||
<!-- <div slot="hander_handle">
|
||||
<div @click="changeInputRadio"><span class="iconfont" :class="{ selected: inputRadio }"></span></div>
|
||||
</div> -->
|
||||
<div slot="content" class="content">
|
||||
<div class="content_header">
|
||||
<div class="content_header_avar"><image :src="userDetilsData.avatar" mode="widthFix"></image></div>
|
||||
<div class="content_header_userName">
|
||||
<span>{{ userDetilsData.nickname }}</span>
|
||||
</div>
|
||||
<div class="content_header_tag">
|
||||
<span>{{ formType[userDetilsData.type] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_message">
|
||||
<div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>备注昵称</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<input type="text" v-model="userDetilsData.remark_nickname" placeholder="请输入备注昵称" v-if="inputRadio" />
|
||||
<span v-else>{{ userDetilsData.remark_nickname ? userDetilsData.remark_nickname : '暂无数据' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>手机号</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<input type="text" v-model="userDetilsData.phone" placeholder="请输入客户联系方式" v-if="inputRadio" />
|
||||
<span v-else>{{ userDetilsData.phone ? userDetilsData.phone : '暂无数据' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>性别</span></div>
|
||||
|
||||
<div class="content_message_item_value" v-if="inputRadio">
|
||||
<picker mode="selector" :range="sexArr" range-key="label" @change="changeSex">
|
||||
<view>{{ sexType[userDetilsData.sex] }}</view>
|
||||
</picker>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item_value" v-else>
|
||||
<span>{{ sexType[userDetilsData.sex] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>备注</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<input type="text" v-model="userDetilsData.remarks" placeholder="请输入备注" v-if="inputRadio" />
|
||||
<span v-else>{{ userDetilsData.remarks ? userDetilsData.remarks : '暂无数据' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content_message_item" @click="openUserTag">
|
||||
<div class="content_message_item_label"><span>用户标签</span></div>
|
||||
<div class="content_message_item_value flex">
|
||||
<div class="tag_list">
|
||||
<span v-for="(item, index) in userDetilsData.label" :key="index">{{ item.label }}</span>
|
||||
</div>
|
||||
<div class="to_link" v-if="inputRadio"><span class="iconfont font"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content_message_item" @click="editGroup">
|
||||
<div class="content_message_item_label"><span>分组</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<span>{{ userGroupConcat[userDetilsData.group_id] }}</span>
|
||||
</div>
|
||||
<div class="to_link" v-if="inputRadio"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>用户类型</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<span>{{ formType[userDetilsData.type] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="content_message_item">
|
||||
<div class="content_message_item_label"><span>生日</span></div>
|
||||
<div class="content_message_item_value"><span>9月5号</span></div>
|
||||
</div> -->
|
||||
|
||||
<div class="content_message_item marginTop16" @click="handelComplaint">
|
||||
<div class="content_message_item_label"><span>投诉</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<span>{{ formType[userDetilsData.type] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_message_item marginTop16" @click="handelblock">
|
||||
<div class="content_message_item_label"><span>拉黑</span></div>
|
||||
<div class="content_message_item_value">
|
||||
<span>{{ formType[userDetilsData.type] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="userTag_container_handle" v-if="inputRadio" @click="handleEditUserMessage">
|
||||
<div class="userTag_container_handle_button"><span>确认修改</span></div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="userTag_container_handle" @click="toMessage">
|
||||
<div class="userTag_container_handle_button"><span>发消息</span></div>
|
||||
</div> -->
|
||||
</div>
|
||||
</lay-out>
|
||||
|
||||
<uni-popup ref="userTagModel" type="center" animation>
|
||||
<div class="userTag_container">
|
||||
<div class="userTag_container_title">
|
||||
<div class="userTag_container_title_message"><span>用户标签</span></div>
|
||||
<div class="closeModel" @click="closeUserTagModel"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<div class="userTag_container_list">
|
||||
<div class="userTag_container_list_item" :class="{ mg40: index == 0 }" v-for="(item, index) in userTagList" :key="index">
|
||||
<div class="userTag_container_list_item_label">
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="userTag_container_list_item_value">
|
||||
<span :class="{ select: val.disabled }" v-for="(val, i) in item.label" :key="i" @click="selectTags(val)">{{ val.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="userTag_container_handle" @click="handleSetTags">
|
||||
<div class="userTag_container_handle_button" ><span>确定</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="userGroupModel" type="center" animation>
|
||||
<div class="userTag_container">
|
||||
<div class="userTag_container_title">
|
||||
<div class="userTag_container_title_message"><span>用户分组</span></div>
|
||||
<div class="closeModel" @click="closeUserGroupModel"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
<div class="userTag_container_list">
|
||||
<div class="userTag_container_list_item">
|
||||
<div class="userTag_container_list_item_value">
|
||||
<span :class="{ select: val.id == selectGroupId }" v-for="(val, i) in userGroup" :key="i" @click="selectGroup(val)">{{ val.group_name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="userTag_container_handle" @click="handleSetGroup">
|
||||
<div class="userTag_container_handle_button"><span>确定</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Toast, navigateTo, Modal } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
inputRadio: true,
|
||||
selectGroupId: '',
|
||||
userTagList: [],
|
||||
formType: {
|
||||
0: 'pc',
|
||||
1: '微信',
|
||||
2: '小程序',
|
||||
3: 'H5'
|
||||
},
|
||||
sexType: {
|
||||
0: '未知',
|
||||
1: '男',
|
||||
2: '女'
|
||||
},
|
||||
sexArr: [
|
||||
{
|
||||
value: 0,
|
||||
label: '未知'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: '男'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: '女'
|
||||
}
|
||||
],
|
||||
userGroup: [], // 用户分组
|
||||
userGroupConcat: {},
|
||||
queryUserData: {}, // url上挂载的参数
|
||||
userDetilsData: {} // 用户详细信息
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.queryUserData = opt;
|
||||
this.initUserGroup();
|
||||
},
|
||||
onNavigationBarButtonTap() {
|
||||
this.handleEditUserMessage();
|
||||
},
|
||||
methods: {
|
||||
// 拉黑
|
||||
handelblock() {
|
||||
Modal('拉黑用户', `"${this.userDetilsData.nickname}"将被拉黑,请问是否继续?`).then(() => {
|
||||
http(api.putUserStatus, { userId: this.userDetilsData.user_id }).then(res => {
|
||||
Toast('拉黑成功');
|
||||
this.$store.commit('setRefresh', true);
|
||||
navigateTo(4, '/pages/view/messageList/index');
|
||||
});
|
||||
});
|
||||
},
|
||||
// 点击投诉按钮,跳转投诉界面
|
||||
handelComplaint() {
|
||||
navigateTo(1, '/pages/view/customerServer/complaint?id='+this.userDetilsData.id);
|
||||
},
|
||||
// 获取用户详细信息
|
||||
initData() {
|
||||
console.log(this.queryUserData);
|
||||
http(api.userInfo, this.queryUserData).then(res => {
|
||||
this.userDetilsData = res;
|
||||
this.selectGroupId = this.userDetilsData.group_id;
|
||||
});
|
||||
},
|
||||
// inputRadio 为 true 时,可以修改客户信息
|
||||
changeInputRadio() {
|
||||
this.inputRadio = !this.inputRadio;
|
||||
},
|
||||
// 获取所有分组 ---> 获取详细信息
|
||||
initUserGroup() {
|
||||
http(api.UserGroup).then(res => {
|
||||
this.userGroup = res;
|
||||
this.userGroup.forEach(item => {
|
||||
this.userGroupConcat[item.id] = item.group_name;
|
||||
});
|
||||
this.initData();
|
||||
});
|
||||
},
|
||||
// 打开用户标签选择选项
|
||||
openUserTag() {
|
||||
if (!this.inputRadio) {
|
||||
Toast('请打开修改开关');
|
||||
return;
|
||||
}
|
||||
http(api.userLabelSelect, { id: this.queryUserData.user_id }).then(res => {
|
||||
this.userTagList = res;
|
||||
this.$refs.userTagModel.open('center');
|
||||
});
|
||||
},
|
||||
// 选择标签
|
||||
selectTags(item) {
|
||||
this.$set(item, 'disabled', !item.disabled);
|
||||
},
|
||||
// 选择性别
|
||||
changeSex(e) {
|
||||
this.userDetilsData.sex = e.detail.value;
|
||||
},
|
||||
// 选择分组弹框
|
||||
editGroup() {
|
||||
if (!this.inputRadio) {
|
||||
Toast('请打开修改开关');
|
||||
return;
|
||||
}
|
||||
this.$refs.userGroupModel.open();
|
||||
},
|
||||
// 关闭选择分组
|
||||
closeUserGroupModel() {
|
||||
this.$refs.userGroupModel.close();
|
||||
},
|
||||
// 选择分组
|
||||
selectGroup(item) {
|
||||
if (this.selectGroupId == item.id) {
|
||||
this.selectGroupId = '';
|
||||
return;
|
||||
}
|
||||
this.selectGroupId = item.id;
|
||||
},
|
||||
// 确认选择分组
|
||||
handleSetGroup() {
|
||||
this.userDetilsData.group_id = this.selectGroupId;
|
||||
http(api.setUserGroup, {
|
||||
id: this.userDetilsData.group_id,
|
||||
userId: this.userDetilsData.id
|
||||
}).then(res => {
|
||||
Toast('用户分组设置完成');
|
||||
this.$refs.userGroupModel.close();
|
||||
});
|
||||
},
|
||||
// 设置标签
|
||||
handleSetTags() {
|
||||
let postData = {
|
||||
label_ids: [],
|
||||
un_label_ids: [],
|
||||
userId: this.queryUserData.user_id
|
||||
},Label = [];
|
||||
|
||||
this.userTagList.forEach(item => {
|
||||
item.label.forEach(val => {
|
||||
if (val.disabled) {
|
||||
postData.label_ids.push(val.id);
|
||||
Label.push(val)
|
||||
} else {
|
||||
postData.un_label_ids.push(val.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
http(api.putUserLabel, postData).then(res => {
|
||||
this.$refs.userTagModel.close();
|
||||
// this.initData();
|
||||
this.selectGroupId = postData.label_ids
|
||||
this.userDetilsData.label = Label
|
||||
});
|
||||
},
|
||||
// 关闭用户标签选项
|
||||
closeUserTagModel() {
|
||||
this.$refs.userTagModel.close();
|
||||
},
|
||||
// 确认修改用户信息
|
||||
handleEditUserMessage() {
|
||||
http(api.userUpdateUser, { ...this.userDetilsData, userId: this.userDetilsData.id }).then(res => {
|
||||
// this.inputRadio = !this.inputRadio;
|
||||
this.initUserGroup();
|
||||
Toast('修改成功');
|
||||
});
|
||||
},
|
||||
toMessage() {
|
||||
navigateTo('2', '/pages/view/customerServer/index', this.queryUserData);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('./less/customerMessage.less');
|
||||
</style>
|
||||
@@ -0,0 +1,651 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<lay-out id='layOut' ref="layOut" :scrollTop="scrollTop" :scrollWithAnimation="false" @goTop="goTop"
|
||||
@layoutScroll="scroll">
|
||||
<!-- #ifdef H5 -->
|
||||
<view slot="header" class="header">
|
||||
<view class="header_left" @click="goBackToMessageList"><span class="iconfont icon-fanhui"></span></view>
|
||||
<view class="header_center">
|
||||
{{ userData.remark_nickname ? userData.remark_nickname : userData.nickname }}
|
||||
</view>
|
||||
<view class="header_right" @click="selectCustomerServerOfTopRight(userData)"><span
|
||||
class="iconfont"></span></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view slot="content" class="content" id="contentMessage">
|
||||
<view class="content_list" v-for="(item, index) in messageList" :key="index"
|
||||
:class="{ right_box: customerServerData.user_ids && customerServerData.user_ids.indexOf(item.user_id) !== -1 }">
|
||||
<view class="content_list_avar" @click="selectCustomerServer(item)">
|
||||
<image :src="item.avatar" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="content_list_message">
|
||||
<view class="content_list_message_value" v-if="item.msn_type <= 2"><text selectable="true"
|
||||
v-html="replace_em(item.msn)"></text></view>
|
||||
<view class="content_list_message_product" v-if="item.msn_type == 5">
|
||||
<view class="content_list_message_orderId">
|
||||
<span class="content_list_message_orderId_label">商品名称:</span>
|
||||
<span class="content_list_message_orderId_value">{{ item.other.store_name }}</span>
|
||||
</view>
|
||||
|
||||
<view class="content_list_message_detils">
|
||||
<view class="content_list_message_detils_image">
|
||||
<image :src="item.other.image" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="content_list_message_detils_value">
|
||||
<view class="content_list_message_detils_value_shopMessag">
|
||||
<view class="content_list_message_detils_value_shopMessag_item">
|
||||
<view class="content_list_message_detils_value_shopMessag_item_label">
|
||||
<span>库存:</span>
|
||||
</view>
|
||||
<view class="content_list_message_detils_value_shopMessag_item_value">
|
||||
<span>{{ item.other.stock }}</span>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content_list_message_detils_value_shopMessag_item">
|
||||
<view class="content_list_message_detils_value_shopMessag_item_label">
|
||||
<span>销量:</span>
|
||||
</view>
|
||||
<view class="content_list_message_detils_value_shopMessag_item_value">
|
||||
<span>{{ parseInt(item.other.sales) + parseInt(item.other.ficti ? item.other.ficti : 0) }}</span>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content_list_message_detils_value_shopPrice">
|
||||
<span>¥{{ item.other.price }}</span>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content_list_message_image" v-if="item.msn_type == 3">
|
||||
<image @load="imageLoad" :src="item.msn" mode="widthFix" @click="showImage(item.msn)">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="chat_result" v-if="item.user_id == customerServerData.user_id">
|
||||
<view class="chat_result_ing" v-if="item.is_send == 0">
|
||||
<!-- 正在发送 -->
|
||||
<view></view>
|
||||
</view>
|
||||
<view class="chat_result_faile" v-if="item.is_send == -1">
|
||||
<!-- 发送失败 -->
|
||||
<view>!</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view slot="bottom" class="footer" :class="{ translateY0: selectModel }">
|
||||
<view class="footer_input">
|
||||
<view class="footer_input_icon mr18" @click="selectScriptLibary"><span
|
||||
class="iconfont"></span></view>
|
||||
<view class="footer_input_content mr18">
|
||||
<textarea v-model="sendMessage" @input="textareaChange($event)" @focus="textareaFocus"
|
||||
class="font" value="" @confirm="sendText" auto-height confirm-type="send"
|
||||
:focus="sendMessageFocus" placeholder="" />
|
||||
<!-- <p v-html="pCont" class="font"></p> -->
|
||||
<!-- <span class="iconfont" :class="{ canSend: sendMessage }" @click="sendText"></span> -->
|
||||
</view>
|
||||
<view class="footer_input_icon">
|
||||
<span class="iconfont mr18" @click="selectOption(1)"></span>
|
||||
<span class="sendMessage" v-if="sendMessage" @click.stop="sendText">发送</span>
|
||||
<span class="iconfont" @click="selectOption(2)" v-if="!sendMessage"></span>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="footer_option" :style="{ height: selectModel ? '440rpx' : '0' }">
|
||||
<view class="option" v-if="selectModel == 2">
|
||||
<view @click="uploadImage">
|
||||
<image src="~static/image/messageList/picture.png" mode="widthFix"></image>
|
||||
<view>图片</view>
|
||||
</view>
|
||||
<view @click="transfer">
|
||||
<image src="~static/image/messageList/connection.png" mode="widthFix"></image>
|
||||
<view>转接</view>
|
||||
</view>
|
||||
<view @click="authReply">
|
||||
<image src="~static/images/auth-reply.png" mode="widthFix"></image>
|
||||
<view>自动回复</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="emoji" v-if="selectModel == 1" scroll-y>
|
||||
<view class="emoji-item" v-for="(item, index) in emoji" :key="index" @click="sendEmoji(item)"><i
|
||||
class="em" :class="item"></i></view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</lay-out>
|
||||
|
||||
<uni-popup ref="transferModel" animation type="bottom">
|
||||
<transfer @close="transferModelClose" :userInfo="userData" @handleSubmit="handleSubmitTransfer"></transfer>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="scriptLibaryModel" animation type="bottom">
|
||||
<view class="scriptLibary">
|
||||
<view class="scriptLibary_header">
|
||||
<view class="scriptLibary_header_title">
|
||||
<view class="tit" v-for="(item, index) in speechArtTypeList" :key="index" @click="selectSpeechArtType(item)"
|
||||
:class="{ speechArtSelectEd: speechArtType == item.id }">
|
||||
<span>{{ item.label }}</span>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="scriptLibary_header_icon">
|
||||
<view @click="editScript"><span class="iconfont icon_edit"></span></view>
|
||||
<view @click="closeScript"><span class="iconfont"></span></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="scriptLibary_search">
|
||||
<view class="search">
|
||||
<span @click="handleSetTitle" class="iconfont icon_search"></span>
|
||||
<input v-model="scriptTitle" type="text" placeholder="搜索快捷回复" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="scriptLibary_content">
|
||||
<scripts-libary :tagList="speechTagList" :speechArtType="speechArtType" maxHeight="1000rpx"
|
||||
height="900rpx" :title="scriptTitle" @sendSpeechMessage="sendSpeechMessage"></scripts-libary>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="showImage" animation type="center">
|
||||
<view class="image_content">
|
||||
<span class="iconfont" @click="closeImage"></span>
|
||||
<image :src="selectMessageImage" mode="widthFix"></image>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import emoji from 'pages/utils/emoji.js';
|
||||
import {
|
||||
navigateBack,
|
||||
navigateTo,
|
||||
serialize,
|
||||
chooseImage,
|
||||
Toast,
|
||||
Modal
|
||||
} from 'pages/utils/uniApi.js';
|
||||
import transfer from './component/transfer.vue';
|
||||
import scriptsLibary from './component/scriptLibary.vue';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import {
|
||||
mapGetters
|
||||
} from 'vuex';
|
||||
const app = getApp();
|
||||
export default {
|
||||
components: {
|
||||
transfer, // 转接客服
|
||||
scriptsLibary // 话术库
|
||||
},
|
||||
computed: mapGetters(['chatList', 'token']),
|
||||
data() {
|
||||
return {
|
||||
selectMessageImage: '', // 选中的图片
|
||||
sendMessageFocus: false,
|
||||
pCont: '',
|
||||
sendMessage: '', // 发送的消息
|
||||
selectModel: 0, // 1:选择表情 2: 功能选择(转接,上传图片)
|
||||
emoji: [],
|
||||
messageList: [],
|
||||
userData: {},
|
||||
pageData: {
|
||||
limit: 20,
|
||||
upperId: 0
|
||||
},
|
||||
speechArtType: 1, // 0 全局 1 私有
|
||||
speechTagList: [], // 话术分类
|
||||
scriptTitle: '', // 搜索输入的内容
|
||||
propstitle: '',
|
||||
speechArtTypeList: [{
|
||||
id: 1,
|
||||
label: '个人库'
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
label: '公共库'
|
||||
}
|
||||
],
|
||||
customerServerData: {
|
||||
user_ids: []
|
||||
},
|
||||
scrollTop: 0, // 滚动位置
|
||||
refresherTriggered: true, // 下拉刷新装状态
|
||||
audioFun: '', // 音频对象
|
||||
old: {
|
||||
scrollTop: 0
|
||||
},
|
||||
kefuInfo: {}, //当前客服信息
|
||||
userId: 0, //当前用户user_id
|
||||
toChatSend: false //是否发送过to_chat
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
messageList: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.messageList.map((item, index) => {
|
||||
if (index) {
|
||||
if (item.add_time - this.messageList[index - 1].add_time >= 300) {
|
||||
item.show = true;
|
||||
} else {
|
||||
item.show = false;
|
||||
}
|
||||
} else {
|
||||
item.show = true;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.emoji = emoji;
|
||||
this.userId = opt.to_user_id;
|
||||
if (!this.userId) {
|
||||
return navigateBack(1);
|
||||
}
|
||||
this.customerServerData = this.$store.getters.kefuInfo;
|
||||
console.log(this.customerServerData)
|
||||
this.kefuInfo = this.$store.getters.kefuInfo;
|
||||
this.messageList = this.$store.getters.chatLog(this.userId);
|
||||
this.userData = this.$store.getters.userInfo(this.userId);
|
||||
this.getUserInfo();
|
||||
this.getKefuInfo();
|
||||
this.initData();
|
||||
this.sockEventListenr();
|
||||
this.$store.dispatch('updataUserCount').then(res => {
|
||||
this.scoket.setBadgeNumber(res.count);
|
||||
});
|
||||
},
|
||||
onUnload() {
|
||||
console.log('聊天界面卸载');
|
||||
uni.$off('chat', this.chatEvent);
|
||||
uni.$off('chat_auth', this.chatAuthEvent);
|
||||
uni.$off('reply', this.replyEvent);
|
||||
uni.$off('success', this.successTochat);
|
||||
uni.$off('close', this.closeEvent);
|
||||
uni.$off('rm_transfer', this.rmTransferEvent);
|
||||
this.toChatSend = false;
|
||||
this.scoket.send({
|
||||
data: {
|
||||
id: 0
|
||||
},
|
||||
type: 'to_chat'
|
||||
});
|
||||
},
|
||||
// 监听,点击界面右上角的按钮
|
||||
onNavigationBarButtonTap(e) {
|
||||
this.selectCustomerServerOfTopRight();
|
||||
},
|
||||
|
||||
methods: {
|
||||
authReply() {
|
||||
navigateTo(1, '/pages/view/authReply/index');
|
||||
},
|
||||
getKefuInfo() {
|
||||
this.$store.dispatch('getKeufuInfo').then(res => {
|
||||
this.kefuInfo = res;
|
||||
});
|
||||
},
|
||||
//获取用户信息
|
||||
getUserInfo() {
|
||||
this.$store
|
||||
.dispatch('getUserInfo', this.userId)
|
||||
.then(res => {
|
||||
this.userData = res; // 获取用户信息
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.userData.remark_nickname ? this.userData.remark_nickname : this
|
||||
.userData.nickname
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.userData.remark_nickname ? this.userData.remark_nickname : this
|
||||
.userData.nickname
|
||||
});
|
||||
});
|
||||
},
|
||||
scroll(value) {
|
||||
this.old.scrollTop = value;
|
||||
},
|
||||
successTochat() {
|
||||
console.log(this.toChatSend);
|
||||
//没发过在发送to_chat
|
||||
if (!this.toChatSend) {
|
||||
this.scoket.send({
|
||||
data: {
|
||||
id: this.userId
|
||||
},
|
||||
type: 'to_chat'
|
||||
});
|
||||
this.toChatSend = true;
|
||||
}
|
||||
},
|
||||
replyEvent(data) {
|
||||
this.pushMessageToList(data);
|
||||
},
|
||||
chatAuthEvent(data) {
|
||||
if (data.length) {
|
||||
data.map(item => {
|
||||
item.msn = this.replace_em(item.msn);
|
||||
this.pushMessageToList(item);
|
||||
})
|
||||
}
|
||||
},
|
||||
chatEvent(data) {
|
||||
this.messageList.map(item => {
|
||||
if (item.guid === data.guid) {
|
||||
item.is_send = 1;
|
||||
}
|
||||
});
|
||||
this.$store.commit('delChatList', {
|
||||
id: this.userId,
|
||||
guid: data.guid
|
||||
});
|
||||
},
|
||||
closeEvent() {
|
||||
this.toChatSend = false;
|
||||
},
|
||||
rmTransferEvent(data) {
|
||||
if (data.recored.to_user_id == this.userId) {
|
||||
navigateBack(1);
|
||||
}
|
||||
},
|
||||
// socket监听
|
||||
sockEventListenr() {
|
||||
if (!this.toChatSend && this.scoket.connectStatus) {
|
||||
this.scoket.send({
|
||||
data: {
|
||||
id: this.userId
|
||||
},
|
||||
type: 'to_chat'
|
||||
});
|
||||
this.toChatSend = true;
|
||||
}
|
||||
uni.$on('success', this.successTochat);
|
||||
uni.$on('chat', this.chatEvent);
|
||||
uni.$on('chat_auth', this.chatAuthEvent);
|
||||
uni.$on('reply', this.replyEvent);
|
||||
uni.$on('close', this.closeEvent);
|
||||
uni.$on('rm_transfer', this.rmTransferEvent);
|
||||
},
|
||||
|
||||
// 获取聊天列表
|
||||
initData() {
|
||||
this.$store
|
||||
.dispatch('getChatLogList', {
|
||||
user_id: this.userId,
|
||||
pageData: this.pageData
|
||||
})
|
||||
.then(res => {
|
||||
let upperId = this.pageData.upperId;
|
||||
this.messageList = upperId === 0 ? res : res.concat(this.messageList);
|
||||
this.pageData.upperId = this.messageList.length ? this.messageList[0].id : 0;
|
||||
if (this.chatList[this.userId]) {
|
||||
this.chatList[this.userId].map(item => {
|
||||
this.messageList.push(item);
|
||||
});
|
||||
}
|
||||
if (upperId === 0) {
|
||||
this.$nextTick(() => {
|
||||
this.goBottom();
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
if (this.chatList[this.userId]) {
|
||||
this.chatList[this.userId].map(item => {
|
||||
this.messageList.push(item);
|
||||
});
|
||||
}
|
||||
if (upperId === 0) {
|
||||
this.$nextTick(() => {
|
||||
this.goBottom();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
// 滑动到顶部
|
||||
goTop() {
|
||||
this.refresherTriggered = true;
|
||||
this.initData();
|
||||
},
|
||||
|
||||
// 发送文本消息
|
||||
sendText(e) {
|
||||
if (this.sendMessage) {
|
||||
// this.sendMessageFocus = true;
|
||||
this.sendMsg(this.sendMessage, 1);
|
||||
this.sendMessage = '';
|
||||
} else {
|
||||
return;
|
||||
// Toast('请输入要发送的消息');
|
||||
}
|
||||
},
|
||||
// 选择表情
|
||||
sendEmoji(item) {
|
||||
this.sendMessage += `[${item}]`;
|
||||
},
|
||||
// 发送图片
|
||||
uploadImage() {
|
||||
let that = this;
|
||||
chooseImage(1).then(res => {
|
||||
//#ifndef H5
|
||||
uni.compressImage({
|
||||
src: res.tempFilePaths[0],
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
success(res) {
|
||||
that.upload(res.tempFilePath);
|
||||
},
|
||||
fail(e) {
|
||||
console.log(e);
|
||||
that.upload(res.tempFilePaths[0]);
|
||||
}
|
||||
});
|
||||
//#endif
|
||||
//#ifdef H5
|
||||
that.upload(res.tempFilePaths[0]);
|
||||
//#endif
|
||||
});
|
||||
},
|
||||
upload(tempFilePath) {
|
||||
uni.uploadFile({
|
||||
url: app.globalData.http + api.kefuUploadAvatar.url,
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
// file: res.tempFilePaths[0],
|
||||
filename: 'file'
|
||||
},
|
||||
header: {
|
||||
// #ifdef MP || APP-PLUS
|
||||
'Content-Type': 'multipart/form-data',
|
||||
// #endif
|
||||
'Authori-zation': 'Bearer ' + this.$store.state.token
|
||||
},
|
||||
success: uploadFileRes => {
|
||||
let unloadResponse = JSON.parse(uploadFileRes.data);
|
||||
console.log(unloadResponse);
|
||||
if (unloadResponse.status == 200) {
|
||||
this.sendMsg(unloadResponse.data.url, 3);
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
Toast('发送图片失败');
|
||||
},
|
||||
complete: res => {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
pushMessageToList(data) {
|
||||
this.messageList.push(data);
|
||||
this.$nextTick(() => {
|
||||
this.goBottom();
|
||||
});
|
||||
},
|
||||
imageLoad() {
|
||||
|
||||
},
|
||||
goBottom() {
|
||||
this.$nextTick(() => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query
|
||||
.select('#contentMessage')
|
||||
.boundingClientRect(data => {
|
||||
this.scrollTop = this.old.scrollTop;
|
||||
this.scrollTop = data.height + 50;
|
||||
console.log(data, this.scrollTop);
|
||||
|
||||
})
|
||||
.exec();
|
||||
});
|
||||
},
|
||||
// textarea获取焦点
|
||||
textareaFocus() {
|
||||
this.selectModel = 0;
|
||||
this.$nextTick(() => {
|
||||
this.goBottom();
|
||||
});
|
||||
},
|
||||
chatOptinos(guid, msn, type, other) {
|
||||
return {
|
||||
msn,
|
||||
msn_type: type,
|
||||
to_user_id: this.userId,
|
||||
is_send: 0,
|
||||
is_tourist: 0,
|
||||
avatar: this.kefuInfo.avatar,
|
||||
user_id: this.kefuInfo.user_id,
|
||||
appid: this.kefuInfo.appid,
|
||||
other: other || {},
|
||||
type: 0,
|
||||
guid
|
||||
};
|
||||
},
|
||||
// 发送消息统一处理
|
||||
sendMsg(msn, type) {
|
||||
let guid = this.scoket.guid();
|
||||
let chat = this.chatOptinos(guid, msn, type);
|
||||
this.$store.commit('setChatList', {
|
||||
id: this.userId,
|
||||
list: chat
|
||||
});
|
||||
chat.msn = this.replace_em(msn);
|
||||
this.pushMessageToList(chat);
|
||||
http(api.sendMessage, {
|
||||
guid,
|
||||
msn,
|
||||
msn_type: type,
|
||||
to_user_id: this.userId,
|
||||
}).then(data => {
|
||||
this.chatEvent({
|
||||
guid: data.guid
|
||||
});
|
||||
})
|
||||
|
||||
},
|
||||
selectScriptLibary() {
|
||||
this.$refs.scriptLibaryModel.open();
|
||||
},
|
||||
// 选择话术库,个人,工共
|
||||
selectSpeechArtType(item) {
|
||||
this.speechArtType = item.id;
|
||||
this.selectScriptLibary();
|
||||
},
|
||||
// 选中话术
|
||||
sendSpeechMessage(item) {
|
||||
this.sendMessage = item.message;
|
||||
this.$refs.scriptLibaryModel.close(); // 关闭话术库弹框
|
||||
},
|
||||
// 关闭话术弹框
|
||||
closeScript() {
|
||||
this.$refs.scriptLibaryModel.close();
|
||||
},
|
||||
// 修改话术库
|
||||
editScript() {
|
||||
this.$refs.scriptLibaryModel.close();
|
||||
navigateTo(1, '/pages/view/customerServer/script', {
|
||||
speechArtType: this.speechArtType
|
||||
});
|
||||
},
|
||||
// 话术搜索
|
||||
handleSetTitle() {
|
||||
this.propstitle = serialize(this.scriptTitle);
|
||||
},
|
||||
// 转接
|
||||
transfer() {
|
||||
this.selectModel = 0;
|
||||
this.$refs.transferModel.open();
|
||||
},
|
||||
// 确认转接
|
||||
handleSubmitTransfer() {
|
||||
this.$refs.transferModel.close();
|
||||
navigateTo(4, '/pages/view/messageList/index');
|
||||
},
|
||||
// 关闭转接弹框
|
||||
transferModelClose() {
|
||||
this.$refs.transferModel.close();
|
||||
},
|
||||
// 头部方法,回到聊天列表页
|
||||
goBackToMessageList() {
|
||||
navigateTo(4, '/pages/view/messageList/index');
|
||||
},
|
||||
// 查看用户详情
|
||||
selectCustomerServer(item) {
|
||||
if (this.customerServerData.user_ids && this.customerServerData.user_ids.indexOf(item.user_id) === -1) {
|
||||
navigateTo(1, '/pages/view/customerServer/customerMessage', item);
|
||||
}
|
||||
},
|
||||
selectCustomerServerOfTopRight() {
|
||||
navigateTo(1, '/pages/view/customerServer/customerMessage', {
|
||||
user_id: this.userId
|
||||
});
|
||||
},
|
||||
// 选择上传图片,转接
|
||||
selectOption(item) {
|
||||
this.selectModel = item;
|
||||
},
|
||||
// 聊天表情转换
|
||||
replace_em(str) {
|
||||
str = str.replace(/\[em-([\s\S]*)\]/g, "<span class='em em-$1'/></span>");
|
||||
return str;
|
||||
},
|
||||
textareaChange(e) {
|
||||
let strCont = e.target.value.replace(/\n\s(\s)*/gi, '\n'); // 将多个回车换行合并为 1个
|
||||
strCont = strCont.replace(/^\s*/gi, ''); // 清除首行的 空格与换行
|
||||
let strHtml = strCont.replace(/</gi, '<'); // 将所有的 < 转义为 < 防止html标签被转义
|
||||
strHtml = strCont.replace(/\n(\n)*/gi, '<br>'); // 回车换行替换为 <br>
|
||||
strHtml = strHtml.replace(/\s+/gi, ' '); // 一个或过个空格 替换为
|
||||
strCont = strHtml.replace(/ /gi, ' '); // 逆向处理
|
||||
strCont = strCont.replace(/<br>/gi, '\n'); // 逆向处理
|
||||
strCont = strCont.replace(/</gi, '<');
|
||||
/** 如果 p 标签最后的字符为 <br> 并不会单独另起一行, 会导致与 textarea 的高度相差一行,
|
||||
* 所以在最后添加一个字符, 这样就能保证 P 标签的高度与 textarea 的高度一致
|
||||
*/
|
||||
this.pCont = strHtml + '.';
|
||||
},
|
||||
// 点击聊天内容
|
||||
// 点击图片
|
||||
showImage(item) {
|
||||
console.log(item);
|
||||
this.selectMessageImage = item;
|
||||
this.$refs.showImage.open();
|
||||
},
|
||||
closeImage() {
|
||||
this.$refs.showImage.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import './less/customerServer.less';
|
||||
@import './less/scriptLibary.less';
|
||||
</style>
|
||||
@@ -0,0 +1,159 @@
|
||||
.selected {
|
||||
color: @primaryColor !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
.content_header {
|
||||
height: 150rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 30rpx;
|
||||
background: #fff;
|
||||
&_avar {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
margin-right: 22rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
&_userName {
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
&_tag {
|
||||
span {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
color: @primaryColor;
|
||||
background: rgba(56, 117, 234, 0.14);
|
||||
padding: 3rpx 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content_message {
|
||||
margin-top: 14rpx;
|
||||
&_item {
|
||||
display: flex;
|
||||
// height: 100rpx;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
padding: 40rpx 30rpx;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #f0f2f7;
|
||||
&_label {
|
||||
flex: 0.25;
|
||||
}
|
||||
&_value {
|
||||
flex: 0.75;
|
||||
font-weight: 600;
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
.tag_list {
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-row-gap: 20rpx;
|
||||
justify-items: self-start;
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: @primaryColor;
|
||||
display: inline-block;
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 16px;
|
||||
border: 1px solid @primaryColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.marginTop16 {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
}
|
||||
.iconfont {
|
||||
font-weight: 900;
|
||||
color: #c4c4c4;
|
||||
font-size: 20px !important;
|
||||
}
|
||||
.to_link {
|
||||
.iconfont {
|
||||
font-weight: 400;
|
||||
color: #000;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
}
|
||||
.userTag_container {
|
||||
padding: 30rpx 40rpx;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
width: 690rpx;
|
||||
box-sizing: border-box;
|
||||
&_title {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
&_message {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
&_list {
|
||||
&_item {
|
||||
margin-top: 78rpx;
|
||||
&_label {
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
&_value {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 178rpx);
|
||||
grid-row-gap: 26rpx;
|
||||
grid-column-gap: 26rpx;
|
||||
span {
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
background: #f0f0f0;
|
||||
text-align: center;
|
||||
padding: 12rpx 0;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.select {
|
||||
background: @primaryColor;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mg0 {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&_handle {
|
||||
width: 610rpx;
|
||||
height: 76rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
margin: auto;
|
||||
margin-top: 84rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
.header {
|
||||
height: 116rpx;
|
||||
background: linear-gradient(90deg, #3875ea 0%, #1890fc 100%);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 30rpx;
|
||||
|
||||
color: #fff;
|
||||
> view {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
.header_left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&_center {
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, -50%);
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.header_right {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
// 聊天对话框
|
||||
.content {
|
||||
padding: 36rpx 30rpx;
|
||||
&_list {
|
||||
display: flex;
|
||||
margin-bottom: 36rpx;
|
||||
color: #282828;
|
||||
font-weight: 600;
|
||||
&_avar {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
margin-right: 22rpx;
|
||||
border-radius: 50%;
|
||||
// border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&_message {
|
||||
max-width: 420rpx;
|
||||
padding: 15rpx 28rpx;
|
||||
background: #fff;
|
||||
border-radius: 7px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_value{
|
||||
word-break:break-all;
|
||||
word-wrap:break-word;
|
||||
}
|
||||
&_product {
|
||||
.content_list_message_orderId {
|
||||
padding-bottom: 15rpx;
|
||||
border-bottom: 1px solid #eceff8;
|
||||
}
|
||||
|
||||
.content_list_message_detils {
|
||||
padding-top: 20rpx;
|
||||
display: flex;
|
||||
&_image {
|
||||
width: 204rpx;
|
||||
height: 204rpx;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
background: #eee;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&_value {
|
||||
flex: 1;
|
||||
padding-left: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
&_shopPrice {
|
||||
color: #f74c31;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
.content_list_message_detils_value_shopMessag {
|
||||
}
|
||||
|
||||
.content_list_message_detils_value_shopMessag_item {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_image {
|
||||
max-width: 400rpx;
|
||||
image {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.right_box {
|
||||
flex-direction: row-reverse;
|
||||
.content_list_message {
|
||||
margin-right: 20rpx;
|
||||
background: #cde0ff;
|
||||
}
|
||||
|
||||
.content_list_avar {
|
||||
margin-right: 0rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
background: #f3f4f5;
|
||||
padding-bottom: 20rpx;
|
||||
&_input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 30rpx;
|
||||
border-top: 1px solid #dddddd;
|
||||
&_icon {
|
||||
// align-self: flex-start;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 24px;
|
||||
}
|
||||
.mr18 {
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
&_content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
padding: 8rpx;
|
||||
border-radius: 32px;
|
||||
overflow: hidden; // 隐藏超出部分的textarea
|
||||
.font {
|
||||
padding: 8rpx 16rpx;
|
||||
}
|
||||
textarea {
|
||||
height: 20px;
|
||||
display: block;
|
||||
// position: absolute;
|
||||
// top: 0rpx;
|
||||
// left: 0rpx;
|
||||
z-index: 10;
|
||||
resize: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
width: 80%;
|
||||
font-size: 14px;
|
||||
}
|
||||
p {
|
||||
width: 100%;
|
||||
display: block;
|
||||
min-height: 20rpx;
|
||||
opacity: 0;
|
||||
}
|
||||
.iconfont {
|
||||
color: #e0e0e0;
|
||||
}
|
||||
.canSend {
|
||||
color: @primaryColor;
|
||||
}
|
||||
}
|
||||
.footer_input_icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.iconfont {
|
||||
font-size: 60rpx;
|
||||
}
|
||||
.sendMessage {
|
||||
display: inline-block;
|
||||
background: @primaryColor;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
padding: 12rpx 25rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_option {
|
||||
background: #fff;
|
||||
height: 440rpx;
|
||||
transition: 0.3s;
|
||||
.option {
|
||||
padding: 46rpx 65rpx;
|
||||
box-sizing: border-box;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
grid-gap: 68rpx;
|
||||
> view {
|
||||
text-align: center;
|
||||
image {
|
||||
width: 90%;
|
||||
}
|
||||
> view {
|
||||
color: #282828;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emoji {
|
||||
height: 100%;
|
||||
|
||||
.emoji-item {
|
||||
display: inline-block;
|
||||
width: 12.5%;
|
||||
text-align: center;
|
||||
margin: 20rpx 0;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
.em {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.translateY0 {
|
||||
// transform: translateY(0);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.speechArtSelectEd {
|
||||
color: @primaryColor;
|
||||
}
|
||||
|
||||
.image_content {
|
||||
max-width: 90%;
|
||||
margin: auto;
|
||||
position: relative;
|
||||
image {
|
||||
max-width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
span {
|
||||
position: absolute;
|
||||
right: -30rpx;
|
||||
top: -30rpx;
|
||||
z-index: 100;
|
||||
font-size: 60rpx;
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.chat_result_ing {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-top: 1px solid #ccc;
|
||||
border-left: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
animation: changeleft 1s linear infinite;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.chat_result_faile {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: #FF0000;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@keyframes changeleft {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.scriptLibary_header {
|
||||
display: flex;
|
||||
padding: 44rpx 32rpx;
|
||||
position: relative;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.scriptLibary_header_title[data-v-afab33f6] {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
display: flex;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.speechArtSelectEd[data-v-afab33f6] {
|
||||
color: #3875EA;
|
||||
}
|
||||
.scriptLibary_header_icon {
|
||||
display: flex;
|
||||
}
|
||||
.tit {
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
.search {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
background: #f5f6f9;
|
||||
margin: 0 5%;
|
||||
border-radius: 30rpx;
|
||||
padding: 10rpx 0;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.icon_search {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
left: 33%;
|
||||
}
|
||||
.uni-input-placeholder {
|
||||
color: #9f9f9f !important;
|
||||
}
|
||||
.icon_edit {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
.scriptLibary {
|
||||
background: #fff;
|
||||
border-radius: 12rpx 12rpx 0px 0px;
|
||||
&_header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 40rpx 30rpx;
|
||||
position: relative;
|
||||
> div {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&_title {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
> div:nth-child(1) {
|
||||
margin-right: 100rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&_icon {
|
||||
> div:nth-child(1) {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c8cad0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_search {
|
||||
padding-bottom: 44rpx;
|
||||
border-bottom: 1px solid #F0F3FA;
|
||||
> div {
|
||||
display: flex;
|
||||
background: #f5f6f9;
|
||||
width: 690rpx;
|
||||
height: 68rpx;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 39px;
|
||||
> input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #C4C4C4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<div slot="header" class="header">
|
||||
<div class="header_title">{{speechArtTypeConcat[speechArtType]}}</div>
|
||||
<div @click="finish">完成</div>
|
||||
</div>
|
||||
<div slot="content" class="content">
|
||||
<div class="scriptLibary_search">
|
||||
<div>
|
||||
<span class="iconfont"></span>
|
||||
<input v-model="propstitle" type="text" placeholder="搜索快捷回复" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="scriptLibary_content">
|
||||
<scripts-libary
|
||||
:speechArtType="speechArtType"
|
||||
:maxHeight="maxHeight"
|
||||
icCanEdit
|
||||
:tagList="speechTagList"
|
||||
:title="propstitle"
|
||||
></scripts-libary>
|
||||
</div>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import scriptsLibary from './component/scriptLibary.vue';
|
||||
import { navigateTo, navigateBack } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: {
|
||||
scriptsLibary
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
maxHeight: '',
|
||||
speechArtType: '',
|
||||
speechArtTypeConcat: {
|
||||
1: '个人库',
|
||||
0: '公共库'
|
||||
},
|
||||
speechTagList: [], // 话术分类
|
||||
propstitle: ''
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.speechArtType = opt.speechArtType;
|
||||
this.selectScriptLibary();
|
||||
console.log(this.speechArtType);
|
||||
this.$nextTick(() => {
|
||||
let info = uni.createSelectorQuery().select('.content');
|
||||
info
|
||||
.boundingClientRect((data) => {
|
||||
this.maxHeight = (Math.ceil(data.height) * 1.85) + 'rpx'
|
||||
})
|
||||
.exec();
|
||||
})
|
||||
|
||||
},
|
||||
methods: {
|
||||
// 查询话术类
|
||||
selectScriptLibary() {
|
||||
http(api.kefuServiceCate, {
|
||||
type: this.speechArtType
|
||||
}).then(res => {
|
||||
this.speechTagList = res.data;
|
||||
});
|
||||
},
|
||||
finish() {
|
||||
navigateBack(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.header {
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding: 0 30rpx;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
&_title {
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
font-size: 14px;
|
||||
color: @primaryColor;
|
||||
}
|
||||
}
|
||||
.scriptLibary_search {
|
||||
background: #fff;
|
||||
padding-bottom: 44rpx;
|
||||
border-bottom: 1px solid #f0f3fa;
|
||||
> div {
|
||||
display: flex;
|
||||
background: #f5f6f9;
|
||||
width: 690rpx;
|
||||
height: 68rpx;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 39px;
|
||||
> input {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.iconfont {
|
||||
font-size: 22px;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
.scriptLibary_content {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="login_container">
|
||||
<!-- 头部背景图 -->
|
||||
<div class="login_container_bg"><!-- <image class="login_container_bg_image" src="~static/dominName/bg.png" mode="widthFix"></image> --></div>
|
||||
<!-- 头部背景图结束 -->
|
||||
<div class="login_container_content">
|
||||
<div class="login_container_content_title"><span>设置请求域名</span></div>
|
||||
|
||||
<div class="login_container_content_form">
|
||||
<div class="login_container_content_form_input">
|
||||
<picker mode="selector" :range="fileList" @change="chageFile" range-key="label">
|
||||
<view>
|
||||
<span>{{ fileListConcat[selectFile] }}</span>
|
||||
<span>://</span>
|
||||
</view>
|
||||
</picker>
|
||||
<input type="text" v-model="dominName" placeholder="请输入域名" />
|
||||
<!-- <span class="iconfont"></span> -->
|
||||
</div>
|
||||
|
||||
<!-- <div class="login_container_content_form_input">
|
||||
<span>{{wsFileConcat[selectFile]}}</span>
|
||||
<span>://</span>
|
||||
<span>{{dominName}}</span>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div class="login_container_content_handle">
|
||||
<div class="login_button" @click="cancel" v-if="isShowCencel">取消</div>
|
||||
<div class="login_primary_button" @click="handleSetDominName">确定</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { navigateTo, Modal, navigateBack, Toast } from 'pages/utils/uniApi.js';
|
||||
const app = getApp()
|
||||
export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
selectFile: 0,
|
||||
dominName: '',
|
||||
fileList: [
|
||||
{
|
||||
label: 'http',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: 'https',
|
||||
value: 1
|
||||
}
|
||||
],
|
||||
fileListConcat: {
|
||||
0: 'http',
|
||||
1: 'https'
|
||||
},
|
||||
wsFileConcat: {
|
||||
0: 'ws',
|
||||
1: 'wss'
|
||||
},
|
||||
isShowCencel: false
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.$cache.set('pages_dominName', 1);
|
||||
this.$cache.remove('accountData');
|
||||
if (this.$cache.get('dominName')) {
|
||||
this.dominName = this.$cache.get('dominName');
|
||||
if (this.$cache.get('requestFile') == 'http') {
|
||||
this.selectFile = 0;
|
||||
} else {
|
||||
this.selectFile = 1;
|
||||
}
|
||||
this.isShowCencel = true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSetDominName() {
|
||||
if (!this.dominName) {
|
||||
Toast('请设置域名');
|
||||
return;
|
||||
}
|
||||
|
||||
Modal('温馨提示', `您设置的域名是 "${this.dominName}", 请问是否继续?`).then(res => {
|
||||
this.$store.commit('setHttp', {
|
||||
wsFile: this.wsFileConcat[this.selectFile],
|
||||
dominName: this.dominName,
|
||||
requestFile: this.fileListConcat[this.selectFile]
|
||||
});
|
||||
app.globalData.http = this.$store.state.http
|
||||
this.scoket.clearPing();
|
||||
this.$store.commit('clearChat');
|
||||
this.$store.commit('logout');
|
||||
navigateTo(1, '/pages/view/login/index');
|
||||
this.$cache.remove('pages_dominName');
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
navigateBack(1);
|
||||
},
|
||||
chageFile(e) {
|
||||
console.log(e);
|
||||
this.selectFile = e.detail.value;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.login_container {
|
||||
position: relative;
|
||||
&_bg {
|
||||
&_image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&_content {
|
||||
width: 642rpx;
|
||||
padding: 54rpx 79rpx 67rpx 79rpx;
|
||||
// box-shadow: 0px 3px 20px rgba(0, 20, 41, 0.06);
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 209rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
margin: auto;
|
||||
border-radius: 20rpx;
|
||||
&_title {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 54rpx;
|
||||
}
|
||||
&_form {
|
||||
&_input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 96rpx;
|
||||
// background: #f5f5f5;
|
||||
padding: 0 28rpx;
|
||||
// border-radius: 12rpx;
|
||||
input {
|
||||
margin-left: 16rpx;
|
||||
flex: 1;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
> div:nth-child(1) {
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
}
|
||||
&_handle {
|
||||
margin-top: 57rpx;
|
||||
display: flex;
|
||||
.login_primary_button {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
background: @primaryBgColor;
|
||||
border-radius: 41px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
}
|
||||
.login_button {
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
border-radius: 41px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #ccc;
|
||||
margin-right: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<div slot="content" class="content">
|
||||
<div v-for="(item, index) in 100" :key="index">{{index}}</div>
|
||||
</div>
|
||||
<div slot="bottom">asdad</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { navigateTo, formatDate, serialize, showWeekFirstDay, showMonthFirstDay, getQuarterStartDate } from 'pages/utils/uniApi.js';
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
onLoad(opt) {
|
||||
|
||||
},
|
||||
onShow(opt) {
|
||||
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div class="submit_res_container">
|
||||
<div class="image_box"><image src="~static/image/feedback/submitSuccess.png" mode="widthFix"></image></div>
|
||||
<div class="title">
|
||||
<span>提交成功</span>
|
||||
</div>
|
||||
<div class="message">
|
||||
<div>您的信息提交成功</div>
|
||||
<div>我们会尽快与您取得联系!</div>
|
||||
</div>
|
||||
<div class="handle" @click="handleSubmitRes">
|
||||
<span>好的</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods:{
|
||||
handleSubmitRes() {
|
||||
this.$emit('handleSubmitRes')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.submit_res_container {
|
||||
padding: 66rpx 111rpx;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
.image_box {
|
||||
width: 344rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.title {
|
||||
color: #434343;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
margin: 30rpx 0 12rpx 0;
|
||||
}
|
||||
.message {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #9F9F9F;
|
||||
}
|
||||
.handle {
|
||||
width: 426rpx;
|
||||
height: 76rpx;
|
||||
background: @primaryBgColor;
|
||||
opacity: 1;
|
||||
border-radius: 38px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
margin-top: 54rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out headerColor="#3A3A3A" headerTextColor="#fff">
|
||||
<div slot="content" class="content">
|
||||
<div class="header_banner">
|
||||
<div class="header_banner_content">
|
||||
<div class="header_banner_content_title">
|
||||
<span>应用反馈</span>
|
||||
</div>
|
||||
<div class="header_banner_content_message">
|
||||
<span>亲,您有其他对应用的已意见或者您收到不良信息,都可以向时反馈,我们非常重视您给我们提出宝贵的建议,帮助我们不断完善产品,谢谢!</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="header_banner_image">
|
||||
<div class="header_banner_image_imageBox">
|
||||
<image src="~static/image/feedback/bg.png" mode="widthFix"></image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feedback">
|
||||
<div class="feedback_title">
|
||||
<span>我要反馈</span>
|
||||
</div>
|
||||
<div class="feedback_input">
|
||||
<input v-model="feedBackData.rela_name" type="text" value="" placeholder="请输入您的姓名"/>
|
||||
</div>
|
||||
<div class="feedback_input">
|
||||
<input v-model="feedBackData.phone" type="text" value="" placeholder="请输入您的联系电话" />
|
||||
</div>
|
||||
<div class="feedback_textarea">
|
||||
<textarea v-model="feedBackData.content" value="" placeholder="请填写留言内容" />
|
||||
</div>
|
||||
|
||||
<div class="handle_button" @click="handleSubmit">
|
||||
<span>提交</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</lay-out>
|
||||
|
||||
<uni-popup ref="feedbackReslove" animation>
|
||||
<submit-response @handleSubmitRes="handleSubmitRes"></submit-response>
|
||||
</uni-popup>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {navigateBack} from 'pages/utils/uniApi.js'
|
||||
import submitResponse from './component/submitResponse.vue';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: {
|
||||
submitResponse
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
feedBackData: {
|
||||
rela_name: '',
|
||||
phone: '',
|
||||
content: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
},
|
||||
methods: {
|
||||
handleSubmit() {
|
||||
http(api.userFeedback, this.feedBackData).then(res => {
|
||||
this.$refs.feedbackReslove.open('center');
|
||||
})
|
||||
},
|
||||
handleSubmitRes() {
|
||||
navigateBack(1);
|
||||
this.$refs.feedbackReslove.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('./less/feedback.less');
|
||||
</style>
|
||||
@@ -0,0 +1,135 @@
|
||||
.container {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.header_banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx;
|
||||
height: 205rpx;
|
||||
background: #3a3a3a;
|
||||
&_content {
|
||||
flex: 1;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
&_title {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
&_message {
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
&_image {
|
||||
width: 173rpx;
|
||||
height: 173rpx;
|
||||
|
||||
&_imageBox {
|
||||
width: 100%;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.organization_work {
|
||||
display: flex;
|
||||
margin-bottom: 16rpx;
|
||||
&_item {
|
||||
flex: 1;
|
||||
padding: 24rpx 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
&_label {
|
||||
font-size: 16px;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
&_value {
|
||||
color: #9f9f9f;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.tip {
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
.feedback {
|
||||
padding: 28rpx 30rpx;
|
||||
background: #fff;
|
||||
flex: 1;
|
||||
&_title {
|
||||
color: #282828;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
&_input {
|
||||
height: 78rpx;
|
||||
background: #f5f5f5;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 20rpx;
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
&_textarea {
|
||||
height: 260rpx;
|
||||
padding: 19rpx 20rpx;
|
||||
background: #f5f5f5;
|
||||
textarea {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.handle_button {
|
||||
margin-top: 130rpx;
|
||||
width: 690rpx;
|
||||
height: 86rpx;
|
||||
background: #3875ea;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.feedback_list {
|
||||
margin-bottom: 50rpx;
|
||||
&_item {
|
||||
padding: 30rpx 15rpx;
|
||||
display: flex;
|
||||
border-bottom: 1rpx solid #ccc;
|
||||
|
||||
>div:nth-child(1) {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 50%;
|
||||
margin-right: 15rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
&_selected {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background: #3875ea;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<lay-out noBottomHeight>
|
||||
<div slot="header">
|
||||
<view class="search-content padding">
|
||||
<view class="uni-input-wrapper"><input class="uni-input" @confirm="initData" v-model="searchData.nickname" placeholder="搜索用户名称" /></view>
|
||||
</view>
|
||||
</div>
|
||||
|
||||
<div slot="content">
|
||||
<!-- 通讯录导航 -->
|
||||
<address-book :bookList="bookList" :letter="letter">
|
||||
<template v-slot:addressBookList>
|
||||
<view class="user-content">
|
||||
<view class="user-list" v-for="(item, index) in Object.keys(bookList)" :key="index">
|
||||
<view class="number padding">{{ item }}</view>
|
||||
<view class="user" v-for="(val, i) in bookList[item]" :key="i" @click="selectUser(val)">
|
||||
<view class="user-list-left"><image :src="val.avatar" mode=""></image></view>
|
||||
<view class="user-list-right">{{ val.nickname }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</address-book>
|
||||
</div>
|
||||
</lay-out>
|
||||
|
||||
<uni-popup ref="userTagModel" type="bottom" animation>
|
||||
<div class="userTag_container">
|
||||
<div class="userTag_container_title">
|
||||
<div :class="{ on: tabOn == 1 }" class="userTag_container_title_message" @click="tabOn = 1"><span>用户标签</span></div>
|
||||
<div :class="{ on: tabOn == 2 }" class="userTag_container_title_message" @click="tabOn = 2"><span>分组标签</span></div>
|
||||
<div class="closeModel" @click="closeUserTagModel"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
|
||||
<scroll-view scroll-y="true" class="userTag_container_list">
|
||||
<div v-if="tabOn == 1" class="userTag_container_list_item" :class="{ mg40: index == 0 }" v-for="(item, index) in userTagList" :key="index">
|
||||
<div class="userTag_container_list_item_label">
|
||||
<span>{{ item.name }}</span>
|
||||
</div>
|
||||
<div class="userTag_container_list_item_value">
|
||||
<span :class="{ select: val.disabled }" v-for="(val, i) in item.label" :key="i" @click="selectTags(val)">{{ val.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="tabOn == 2" class="userTag_container_list_item mg40">
|
||||
<div class="userTag_container_list_item_value">
|
||||
<span :class="{ select: val.disabled }" v-for="(val, i) in groupList" :key="val" @click="selectGroups(val)">{{ val.group_name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</scroll-view>
|
||||
<div class="userTag_container_handle" @click="handleSetTags">
|
||||
<div class="userTag_container_handle_button"><span>确定</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AddressBook from './addressBookNavigation/addressBookNavigation';
|
||||
import { makePy } from '../../utils/utils';
|
||||
import { navigateTo } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: { AddressBook },
|
||||
data() {
|
||||
return {
|
||||
letter: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
|
||||
list: [],
|
||||
search: '',
|
||||
bookList: {},
|
||||
customerServerData: {}, // 客服数据
|
||||
searchData: {
|
||||
nickname: '',
|
||||
label_id: '',
|
||||
group_id: ''
|
||||
},
|
||||
userTagList: [],
|
||||
groupList: [],
|
||||
tabOn: 1,
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.customerServerData = this.$store.state.kefuInfo;
|
||||
this.bookList = this.$store.state.bookList;
|
||||
},
|
||||
onShow() {
|
||||
this.searchData.label_id = '';
|
||||
this.searchData.group_id = '';
|
||||
this.initData();
|
||||
// { id: this.queryUserData.user_id }
|
||||
http(api.userLabelSelect).then(res => {
|
||||
this.userTagList = res;
|
||||
});
|
||||
http(api.UserGroup).then(res => {
|
||||
this.groupList = res;
|
||||
});
|
||||
},
|
||||
onNavigationBarButtonTap() {
|
||||
// this.toTagList();
|
||||
this.$refs.userTagModel.open();
|
||||
},
|
||||
methods: {
|
||||
// 关闭弹窗
|
||||
closeUserTagModel() {
|
||||
this.$refs.userTagModel.close();
|
||||
},
|
||||
// 选择标签
|
||||
selectTags(item) {
|
||||
this.$set(item, 'disabled', !item.disabled);
|
||||
},
|
||||
selectGroups(item) {
|
||||
this.$set(item, 'disabled', !item.disabled);
|
||||
},
|
||||
// 设置标签
|
||||
handleSetTags() {
|
||||
let postData = {
|
||||
label_ids: [],
|
||||
group_ids: []
|
||||
};
|
||||
console.log(111);
|
||||
this.userTagList.forEach(item => {
|
||||
item.label.forEach(val => {
|
||||
if (val.disabled) {
|
||||
postData.label_ids.push(val.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
this.groupList.forEach(item => {
|
||||
if (item.disabled) {
|
||||
postData.group_ids.push(item.id);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(postData);
|
||||
this.searchData.label_id = postData.label_ids.join(',');
|
||||
this.searchData.group_id = postData.group_ids.join();
|
||||
this.closeUserTagModel();
|
||||
this.initData(this.searchData);
|
||||
},
|
||||
// 查询当前客服的客户列表
|
||||
initData() {
|
||||
this.$store.dispatch('getBookList', this.searchData).then(res => {
|
||||
this.bookList = res;
|
||||
});
|
||||
},
|
||||
|
||||
toTagList() {
|
||||
navigateTo(1, '/pages/view/setTags/index');
|
||||
},
|
||||
selectUser(item) {
|
||||
navigateTo(1, '/pages/view/customerServer/customerMessage', { user_id: item.to_user_id });
|
||||
},
|
||||
// 对通讯录按字母顺序做排序
|
||||
letterSrot() {
|
||||
const sortList = [];
|
||||
const list = this.list;
|
||||
this.letter.forEach(item => {
|
||||
const obj = {};
|
||||
obj.key = item;
|
||||
obj.list = [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (item == makePy(list[i].username).substr(0, 1)) {
|
||||
obj.list.push(list[i]);
|
||||
list.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (obj.list.length) sortList.push(obj);
|
||||
});
|
||||
this.bookList = sortList;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@padding-l-r: 30rpx;
|
||||
@padding-t-p: 20rpx;
|
||||
@bgc-f: #ffffff;
|
||||
@fontSize: 28rpx;
|
||||
@imgSize: 64rpx;
|
||||
.padding {
|
||||
padding: @padding-t-p @padding-l-r;
|
||||
}
|
||||
.search-content {
|
||||
position: relative;
|
||||
background-color: @bgc-f;
|
||||
input {
|
||||
border: none;
|
||||
background-color: #f5f6f9;
|
||||
color: #c4c4c4;
|
||||
font-size: @fontSize;
|
||||
border-radius: 39px;
|
||||
padding: @padding-t-p 0 @padding-t-p @padding-l-r;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.user-content {
|
||||
background-color: #eeeeee;
|
||||
.user-list {
|
||||
.number {
|
||||
color: #666666;
|
||||
font-size: @fontSize - 2rpx;
|
||||
}
|
||||
.user {
|
||||
background-color: @bgc-f;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: @padding-t-p @padding-l-r;
|
||||
border-bottom: 1rpx solid #f0f2f7;
|
||||
.user-list-left {
|
||||
width: @imgSize;
|
||||
height: @imgSize;
|
||||
padding-right: 20rpx;
|
||||
image {
|
||||
width: @imgSize;
|
||||
height: @imgSize;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.user-list-right {
|
||||
color: #282828;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.header {
|
||||
&_content {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 116rpx;
|
||||
background: #1890fc;
|
||||
padding: 0 30rpx;
|
||||
|
||||
/* #ifdef APP-PLUS */
|
||||
padding-top: 64rpx;
|
||||
/* #endif */
|
||||
color: #fff;
|
||||
> div {
|
||||
flex: 1;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
> div:nth-child(3) {
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
.userTag_container {
|
||||
padding: 30rpx 40rpx;
|
||||
// padding-bottom: 140rpx;
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
&_title {
|
||||
display: flex;
|
||||
// justify-content: flex-end;
|
||||
position: relative;
|
||||
&_message {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, -50%);
|
||||
&.on {
|
||||
font-weight: bold;
|
||||
color: #3875EA;
|
||||
}
|
||||
}
|
||||
.closeModel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
color: #c8cad0;
|
||||
.iconfont {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_list {
|
||||
height: 600rpx;
|
||||
&_item {
|
||||
margin-top: 78rpx;
|
||||
&_label {
|
||||
color: #282828;
|
||||
font-weight: bold;
|
||||
margin-bottom: 26rpx;
|
||||
}
|
||||
|
||||
&_value {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 178rpx);
|
||||
grid-row-gap: 26rpx;
|
||||
grid-column-gap: 26rpx;
|
||||
span {
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
background: #f0f0f0;
|
||||
text-align: center;
|
||||
padding: 12rpx 0;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.select {
|
||||
background: @primaryColor;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.mg0 {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&_handle {
|
||||
width: 610rpx;
|
||||
height: 76rpx;
|
||||
background: @primaryColor;
|
||||
opacity: 1;
|
||||
border-radius: 43px;
|
||||
margin: auto;
|
||||
margin-top: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,265 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 右边字母选择导航条 -->
|
||||
<view class="searchLetter touchClass" :style="{ height: itemH * searchLetter.length + 'px', paddingRight: paddingRight + 'upx', width: searchLetterWidth + 'upx' }">
|
||||
<view
|
||||
v-for="(item, index) in searchLetter"
|
||||
:style="{ height: itemH + 'px' }"
|
||||
:key="index"
|
||||
:data-letter="item.name"
|
||||
@touchstart.stop.prevent="searchStart"
|
||||
@touchmove.stop.prevent="searchMove"
|
||||
@touchend.stop.prevent="searchEnd"
|
||||
>
|
||||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 字母选择提示框 -->
|
||||
<block v-if="isShowLetter">
|
||||
<view class="showSlectedLetter">{{ showLetter }}</view>
|
||||
</block>
|
||||
|
||||
<!-- 通讯录列表 -->
|
||||
<scroll-view scroll-y :scrollTop="scrollTop"><slot name="addressBookList"></slot></scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'addressBookNavigation',
|
||||
props: {
|
||||
//通讯录名字集合
|
||||
bookList: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
required: true
|
||||
},
|
||||
//索引集合
|
||||
letter: {
|
||||
type: Array,
|
||||
default() {
|
||||
return ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||
}
|
||||
},
|
||||
//通讯录索引字母显示高度 upx
|
||||
bookKeyHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 100;
|
||||
}
|
||||
},
|
||||
//通讯录名字显示高度 upx
|
||||
bookItemHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 40;
|
||||
}
|
||||
},
|
||||
//右边索引条右边距 upx
|
||||
paddingRight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 20;
|
||||
}
|
||||
},
|
||||
//若有搜索框则是搜索框高度 upx
|
||||
searchHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 20;
|
||||
}
|
||||
},
|
||||
//右边索引条距离搜索框位置 upx
|
||||
searchLetterTop: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 60;
|
||||
}
|
||||
},
|
||||
//右边索引条宽度 upx
|
||||
searchLetterWidth: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 40;
|
||||
}
|
||||
},
|
||||
//减去的右边导航条高度 upx
|
||||
subtractiveSearchLetterHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 80;
|
||||
}
|
||||
},
|
||||
//底部tab高度 使用原生导航栏固定为50px 自定义tab传入自定义tab高度 单位为px
|
||||
tabHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 100;
|
||||
}
|
||||
},
|
||||
//导航栏高度
|
||||
navHeight: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 44;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchLetter: [],
|
||||
//右边索引条单个字母元素高度
|
||||
itemH: 0,
|
||||
//可滑动区域高度
|
||||
usableHeight: 0,
|
||||
screenWidth: 0,
|
||||
isShowLetter: false,
|
||||
showLetter: '',
|
||||
scrollTop: 0,
|
||||
badPageY: uni.upx2px(this.searchHeight + this.searchLetterTop),
|
||||
letterPositionTop: 0,
|
||||
scrollViewPositionTop: 0
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
//#ifdef H5
|
||||
this.letterPositionTop = this.searchHeight + this.searchLetterTop + 88;
|
||||
this.scrollViewPositionTop = this.searchHeight + 88;
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
this.letterPositionTop = this.searchHeight + this.searchLetterTop;
|
||||
this.scrollViewPositionTop = this.searchHeight;
|
||||
//#endif
|
||||
// #ifdef APP-PLUS
|
||||
this.letterPositionTop = this.searchHeight + this.searchLetterTop;
|
||||
this.scrollViewPositionTop = this.searchHeight + 260;
|
||||
console.log(1);
|
||||
// #endif
|
||||
this.countLetterHeight();
|
||||
},
|
||||
methods: {
|
||||
//计算和记录右边每个搜索字母的高度和位置
|
||||
countLetterHeight() {
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
//#ifdef H5
|
||||
const usableHeight = sysInfo.screenHeight - uni.upx2px(this.searchHeight) - this.tabHeight - this.navHeight;
|
||||
//#endif
|
||||
//#ifndef H5
|
||||
const usableHeight = sysInfo.screenHeight - uni.upx2px(this.searchHeight) - this.tabHeight - this.navHeight - sysInfo.statusBarHeight;
|
||||
//#endif
|
||||
this.screenWidth = sysInfo.screenWidth;
|
||||
const letter = this.letter;
|
||||
const itemH = (usableHeight - uni.upx2px(this.subtractiveSearchLetterHeight) - 20) / letter.length;
|
||||
const tempObj = [];
|
||||
for (let i = 0; i < letter.length; i++) {
|
||||
tempObj.push({
|
||||
name: letter[i],
|
||||
tHeight: i * itemH,
|
||||
bHeight: (i + 1) * itemH
|
||||
});
|
||||
}
|
||||
this.usableHeight = usableHeight;
|
||||
this.itemH = itemH;
|
||||
this.searchLetter = tempObj;
|
||||
},
|
||||
searchEnd(e) {
|
||||
const that = this;
|
||||
setTimeout(() => (that.isShowLetter = false), 500);
|
||||
},
|
||||
//点击选择
|
||||
searchStart(e) {
|
||||
console.log(e);
|
||||
const pageY = e.touches[0].pageY - this.badPageY;
|
||||
this.nowLetter(pageY);
|
||||
},
|
||||
//滑动选择
|
||||
searchMove(e) {
|
||||
const pageY = e.touches[0].pageY - this.badPageY;
|
||||
const pageX = e.touches[0].pageX;
|
||||
if (this.screenWidth - pageX > uni.upx2px(this.searchLetterWidth + this.paddingRight)) {
|
||||
this.isShowLetter = false;
|
||||
return;
|
||||
}
|
||||
if (pageY < 0 || pageY > this.itemH * this.searchLetter.length) {
|
||||
this.isShowLetter = false;
|
||||
return;
|
||||
}
|
||||
this.nowLetter(pageY);
|
||||
},
|
||||
//计算当前选中的字母并显示
|
||||
nowLetter(pageY) {
|
||||
const letterData = this.searchLetter;
|
||||
for (let i = 0; i < letterData.length; i++) {
|
||||
if (letterData[i].tHeight <= pageY && pageY <= letterData[i].bHeight) {
|
||||
this.showLetter = letterData[i].name;
|
||||
this.isShowLetter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.scrollPage(this.showLetter);
|
||||
},
|
||||
//计算要滑动的距离
|
||||
countScrollTop(showLetter) {
|
||||
let scrollTop = 0;
|
||||
let cityCount = 0;
|
||||
let initialCount = 0;
|
||||
for (let item of Object.keys(this.bookList)) {
|
||||
if (showLetter == item) {
|
||||
scrollTop = initialCount * uni.upx2px(this.bookKeyHeight) + cityCount * uni.upx2px(this.bookItemHeight);
|
||||
break;
|
||||
} else {
|
||||
initialCount++;
|
||||
cityCount += this.bookList[item].length;
|
||||
}
|
||||
}
|
||||
return scrollTop;
|
||||
},
|
||||
//页面滑动到与选中字母对应的位置
|
||||
scrollPage(showLetter) {
|
||||
const scroll = this.countScrollTop(showLetter);
|
||||
if (scroll != 0 || showLetter == Object.keys(this.bookList)[0]) this.scrollTop = scroll;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.searchLetter {
|
||||
position: fixed;
|
||||
top: 126rpx;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #666;
|
||||
z-index: 999;
|
||||
}
|
||||
.touchClass {
|
||||
color: #5a5a5a;
|
||||
font-size: 28upx;
|
||||
}
|
||||
|
||||
.showSlectedLetter {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 100upx;
|
||||
height: 100upx;
|
||||
border-radius: 10upx;
|
||||
font-size: 44upx;
|
||||
z-index: 99;
|
||||
color: #fff;
|
||||
}
|
||||
scroll-view {
|
||||
// position: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<div class="login_input">
|
||||
<div class="title_icon">
|
||||
<slot name="icon"></slot>
|
||||
</div>
|
||||
<div class="input">
|
||||
<input class="input_model" :placeholder="placeholder" :type="type" v-model="value" @blur="$emit('input', $event.target.value)" />
|
||||
</div>
|
||||
<div class="clear" v-if="value" @click="clear">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'input'
|
||||
},
|
||||
props: {
|
||||
placeholder: {
|
||||
type: String,
|
||||
default:''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: ''
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
clear() {
|
||||
this.value = '';
|
||||
this.$emit('input', '');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.login_input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 22rpx 0;
|
||||
border-bottom: 1px solid #EDEDED;
|
||||
font-size: 14px;
|
||||
.title_icon {
|
||||
margin-right: 12rpx;
|
||||
color: @primaryColor;
|
||||
}
|
||||
.input {
|
||||
flex: 1;
|
||||
&_model {
|
||||
border: none !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
}
|
||||
.clear {
|
||||
opacity: .2;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,161 @@
|
||||
<template>
|
||||
<div class="login_container">
|
||||
<!-- 头部背景图 -->
|
||||
<div class="login_container_bg"><image class="login_container_bg_image" src="~static/image/login/bg.png" mode="widthFix"></image></div>
|
||||
<!-- 头部背景图结束 -->
|
||||
<div class="login_container_content">
|
||||
<div class="login_container_content_title"><span>欢迎登录</span></div>
|
||||
|
||||
<div class="login_container_content_form">
|
||||
<div class="login_container_content_form_input">
|
||||
<login-input v-model="loginData.account" type="text" placeholder="请输入账号"><span slot="icon" class="iconfont"></span></login-input>
|
||||
</div>
|
||||
|
||||
<div class="login_container_content_form_input">
|
||||
<login-input v-model="loginData.password" type="password" placeholder="请输入密码"><span slot="icon" class="iconfont"></span></login-input>
|
||||
</div>
|
||||
|
||||
<div class="login_container_content_form_input privacy_agreement">
|
||||
<div class="privacy_agreement_content">
|
||||
<checkbox-group @change="checkoutPrivaey">
|
||||
<checkbox class="checkbox" :value="isCheckEd" />
|
||||
<span>请阅读并勾选</span>
|
||||
<text @click="showPrivaey">隐私协议</text>
|
||||
</checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="login_container_content_handle"><div class="login_primary_button" @click="handleLogin">登录</div></div>
|
||||
<div v-if='isDomainName' class="login-to-set-domin-name"><navigator hover-class="none" url="/pages/view/dominName/index">修改域名</navigator></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import loginInput from './component/loginInput.vue';
|
||||
import { navigateTo, Modal, Toast } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import config from 'pages/config/app.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
loginInput
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loginData: {
|
||||
account: '',
|
||||
password: ''
|
||||
},
|
||||
cid: '',
|
||||
isCheckEd: '1', // 是否选中隐私协议
|
||||
isCheckEdArr: [],
|
||||
isDomainName: config.isDomainName
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.$cache.remove('accountData');
|
||||
this.$cache.set('pages_login', 1);
|
||||
this.scoket.clearPing()
|
||||
},
|
||||
onUnload() {
|
||||
this.$cache.remove('pages_login');
|
||||
},
|
||||
methods: {
|
||||
async handleLogin() {
|
||||
if (!this.isCheckEdArr.length) {
|
||||
Toast('请勾选隐私协议');
|
||||
return;
|
||||
}
|
||||
//#ifdef APP-PLUS
|
||||
let info = plus.push.getClientInfo();
|
||||
this.cid = info.clientid;
|
||||
this.$cache.set('cid', this.cid);
|
||||
//#endif
|
||||
let loginRes = await http(api.login, { ...this.loginData, client_id: this.cid, is_app: 1 });
|
||||
this.$cache.set('userData', loginRes);
|
||||
this.$store.commit('setToken', loginRes.token);
|
||||
this.$cache.set('accountData', this.loginData);
|
||||
//连接长连接
|
||||
this.scoket.startConnect();
|
||||
this.$cache.remove('pages_login');
|
||||
navigateTo(4, '/pages/view/messageList/index');
|
||||
},
|
||||
// 勾选隐私协议
|
||||
checkoutPrivaey(e) {
|
||||
this.isCheckEdArr = e.detail.value;
|
||||
},
|
||||
// 跳转隐私协议
|
||||
showPrivaey() {
|
||||
navigateTo(1, '/pages/view/privacyAgreement/index');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.login_container {
|
||||
position: relative;
|
||||
&_bg {
|
||||
&_image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&_content {
|
||||
width: 642rpx;
|
||||
padding: 54rpx 79rpx 120rpx 79rpx;
|
||||
box-shadow: 0px 3px 20px rgba(0, 20, 41, 0.06);
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 349rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
margin: auto;
|
||||
border-radius: 20rpx;
|
||||
&_title {
|
||||
text-align: center;
|
||||
font-size: 21px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 54rpx;
|
||||
}
|
||||
&_handle {
|
||||
margin-top: 115rpx;
|
||||
|
||||
.login_primary_button {
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 82rpx;
|
||||
background: @primaryBgColor;
|
||||
border-radius: 41px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.privacy_agreement {
|
||||
margin-top: 30rpx;
|
||||
&_content {
|
||||
font-size: 28rpx;
|
||||
.checkbox {
|
||||
transform: scale(0.7);
|
||||
}
|
||||
text {
|
||||
color: @primaryColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-to-set-domin-name {
|
||||
font-size: 20rpx;
|
||||
padding-top: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,433 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out @goBottom="goBottom" @goTop="goTop" @refresherrefresh="refresherrefresh"
|
||||
:refresherTriggered="refresherTriggered" @refresherrestore="refresherrestore"
|
||||
@refresherabort="refresherabort" :scroll-top="scrollTop">
|
||||
<div slot="header">
|
||||
<!-- 搜索框 -->
|
||||
<div class="content_search">
|
||||
<div class="content_search_box">
|
||||
<div class="icon" @click="searchUser"><span class="iconfont"></span></div>
|
||||
<div class="input">
|
||||
<input class="uni-input" @confirm="searchUser" @focus="searchFocus" @blur="searchBlur"
|
||||
v-model="nickname" type="text" placeholder="搜索用户名称" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div slot="content" class="content">
|
||||
<!-- 聊天列表 -->
|
||||
<div class="content_userMessgae">
|
||||
<uni-swipe-action>
|
||||
<uni-swipe-action-item v-for="(item, index) in userList" :right-options="options"
|
||||
@click="deleteUserRecord($event, index)" :key="item.id">
|
||||
<div :id="`content_userMessgae_item${item.id}`" class="content_userMessgae_item"
|
||||
@click="connentServerForUser(item)">
|
||||
<div class="content_userMessgae_item_avar">
|
||||
<image :src="item.avatar" mode="widthFix"></image>
|
||||
|
||||
<span class="online_status" :class="{ off: item.online }"></span>
|
||||
</div>
|
||||
|
||||
<div class="content_userMessgae_item_value">
|
||||
<div class="content_userMessgae_item_value_user">
|
||||
<div class="content_userMessgae_item_value_user_nickName">{{ item.nickname }}
|
||||
</div>
|
||||
<div class="content_userMessgae_item_value_user_form" v-if="item.type"
|
||||
:class="formType[item.type].className">
|
||||
<span>{{ formType[item.type].label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 用户消息 -->
|
||||
<div class="content_userMessgae_item_value_message">
|
||||
<span>{{ item.message }}</span>
|
||||
</div>
|
||||
<!-- 用户消息结束 -->
|
||||
</div>
|
||||
|
||||
<!-- 聊天时间 -->
|
||||
<div class="content_userMessgae_item_createTime">
|
||||
<div class="content_userMessgae_item_createTime_value">
|
||||
<span>{{ item.update_time | toDay }}</span>
|
||||
</div>
|
||||
<div class="content_userMessgae_item_createTime_count" v-if="item.mssage_num">
|
||||
<span>{{ item.mssage_num }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 聊天时间结束 -->
|
||||
<div class="content_userMessgae_item_del">删除</div>
|
||||
</div>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</div>
|
||||
<!-- <div v-if="!userList.length" class="no_message">
|
||||
<span>暂无客户!</span>
|
||||
</div> -->
|
||||
<!-- 聊天列表结束 -->
|
||||
</div>
|
||||
</lay-out>
|
||||
<div class="fixed_model" v-if="showSearchModel"></div>
|
||||
<download-progress v-show='download' @clearAbort='clearAbort' :percent='percent'></download-progress>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
navigateTo,
|
||||
Modal,
|
||||
formatDate,
|
||||
Toast,
|
||||
parseToObject
|
||||
} from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex';
|
||||
import DownloadProgress from '../../../components/DownloadProgress.vue';
|
||||
export default {
|
||||
filters: {
|
||||
toDay(value) {
|
||||
if (!value) return '';
|
||||
return formatDate(value * 1000, 'M月d日 hh:mm');
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DownloadProgress
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectOnlineStatus: 1,
|
||||
onlineStatus: [{
|
||||
label: '在线',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: '下线',
|
||||
value: 0
|
||||
}
|
||||
],
|
||||
customerServerHandleModel: false, // 客服操作开关
|
||||
customerServerData: {},
|
||||
pageData: {
|
||||
page: 1,
|
||||
limit: 15
|
||||
},
|
||||
formType: {
|
||||
0: {
|
||||
className: 'pc',
|
||||
label: 'pc端'
|
||||
},
|
||||
1: {
|
||||
className: 'gozhonghao',
|
||||
label: '公众号'
|
||||
},
|
||||
2: {
|
||||
className: 'wchat',
|
||||
label: '小程序'
|
||||
},
|
||||
3: {
|
||||
className: 'h5',
|
||||
label: 'H5'
|
||||
}
|
||||
},
|
||||
refresherTriggered: false, // 下拉刷新状态
|
||||
nickname: '',
|
||||
is_tourist: '',
|
||||
userList: [], // 用户列表
|
||||
audioFun: '', // 音频对象
|
||||
showSearchModel: false,
|
||||
lastTapTime: 0,
|
||||
scrollTop: 0,
|
||||
count: 0,
|
||||
userListTemp: {},
|
||||
options: [{
|
||||
text: '取消',
|
||||
style: {
|
||||
backgroundColor: '#007aff'
|
||||
}
|
||||
}, {
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d'
|
||||
}
|
||||
}],
|
||||
download: false,
|
||||
percent: 0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
chatInfo(data) {
|
||||
if (data.id) {
|
||||
let ids = [];
|
||||
this.userList.map(item => {
|
||||
ids.push(item.id);
|
||||
});
|
||||
if (ids.indexOf(data.id) === -1) {
|
||||
this.userList.unshift(data);
|
||||
}
|
||||
this.$store.commit('setChatInfo', {});
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.initSocket();
|
||||
this.userList = this.$store.getters.userRecord.userList;
|
||||
this.appVersionLevel();
|
||||
},
|
||||
onShow(opt) {
|
||||
this.pageData.page = 1;
|
||||
// this.initData(this.pageData.page > 1 ? 'concat' : '');
|
||||
this.initData();
|
||||
this.getKefuInfo();
|
||||
this.updataUserCount();
|
||||
},
|
||||
onUnload() {
|
||||
uni.$off('mssage_num', this.mssageNumEvent);
|
||||
uni.$off('rm_transfer', this.rmTransferEvent);
|
||||
uni.$off('transfer', this.transferEvent)
|
||||
},
|
||||
onTabItemTap(e) {
|
||||
|
||||
},
|
||||
onNavigationBarButtonTap(e) {
|
||||
this.handleScanCode(); // 吊起相机,扫描二维码
|
||||
},
|
||||
computed: {
|
||||
...mapState(['chatInfo', 'kefuInfo', 'config', 'userRecord', 'userLists'])
|
||||
},
|
||||
methods: {
|
||||
appVersionLevel() {
|
||||
// #ifdef APP-PLUS
|
||||
let that = this;
|
||||
plus.runtime.getProperty(plus.runtime.appid, ({
|
||||
version,
|
||||
name
|
||||
}) => {
|
||||
//升级过一次就不要在提醒
|
||||
if (this.$cache.get('update_' + version)) {
|
||||
return;
|
||||
}
|
||||
http(api.appVersion, {
|
||||
version,
|
||||
name
|
||||
}).then(data => {
|
||||
if (data.update === false) {
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
title: '检测到新版本',
|
||||
content: data.info,
|
||||
confirmText: '立即升级',
|
||||
success: (res) => {
|
||||
if (res.confirm && data.update && data.url) {
|
||||
that.downloadFile(data.url);
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
this.$cache.set('update_' + version, 1);
|
||||
}
|
||||
})
|
||||
|
||||
}).catch(res => {})
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
downloadFile(url) {
|
||||
this.downloadTask = uni.downloadFile({
|
||||
url: url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
plus.runtime.install(
|
||||
res.tempFilePath, {
|
||||
force: false
|
||||
}, () => {
|
||||
plus.runtime.restart();
|
||||
}, err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
},
|
||||
complete: () => {
|
||||
this.download = false
|
||||
this.percent = 0;
|
||||
}
|
||||
});
|
||||
this.download = true;
|
||||
this.downloadTask.onProgressUpdate(res => {
|
||||
this.percent = res.progress
|
||||
});
|
||||
},
|
||||
clearAbort() {
|
||||
if (this.downloadTask) {
|
||||
this.downloadTask.abort();
|
||||
this.downloadTask = null;
|
||||
}
|
||||
},
|
||||
// 删除聊天列表用户
|
||||
deleteUserRecord(e, index) {
|
||||
if (e.index == 1) {
|
||||
this.$store.dispatch('deleteUserRecord', {
|
||||
id: this.userList[index].id
|
||||
}).then(res => {
|
||||
this.userList.splice(index, 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
mssageNumEvent(data) {
|
||||
console.log('mssage_num', data);
|
||||
this.getMssageNum(data);
|
||||
},
|
||||
//被转走事件
|
||||
rmTransferEvent(data) {
|
||||
let rmIndex = -1;
|
||||
this.userList.map((item, index) => {
|
||||
if (item.id === data.recored.id) {
|
||||
rmIndex = index;
|
||||
}
|
||||
});
|
||||
if (rmIndex !== -1) {
|
||||
this.userList.splice(rmIndex, 1);
|
||||
this.updataUserCount();
|
||||
}
|
||||
},
|
||||
//转接到当前客服事件
|
||||
transferEvent(data) {
|
||||
let pushIndex = -1;
|
||||
this.userList.map((item, index) => {
|
||||
if (item.id === data.recored.id) {
|
||||
pushIndex = index;
|
||||
}
|
||||
});
|
||||
if (pushIndex === -1) {
|
||||
this.userList.unshift(data.recored);
|
||||
this.updataUserCount();
|
||||
}
|
||||
},
|
||||
initSocket() {
|
||||
uni.$on('mssage_num', this.mssageNumEvent);
|
||||
uni.$on('rm_transfer', this.rmTransferEvent);
|
||||
uni.$on('transfer', this.transferEvent);
|
||||
},
|
||||
getKefuInfo() {
|
||||
this.$store.dispatch('getKeufuInfo').then(res => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: res.site_title
|
||||
});
|
||||
});
|
||||
},
|
||||
// 搜索框获得焦点
|
||||
searchFocus() {
|
||||
this.showSearchModel = true;
|
||||
},
|
||||
// 搜索框失去焦点
|
||||
searchBlur() {
|
||||
this.searchUser();
|
||||
this.showSearchModel = false;
|
||||
},
|
||||
// 搜索用户
|
||||
searchUser() {
|
||||
this.pageData.page = 1;
|
||||
this.initData();
|
||||
},
|
||||
// 获取客户列表, 客服信息
|
||||
initData(type) {
|
||||
this.pageData.limit = 10;
|
||||
this.$store.dispatch('getUserRecord', {
|
||||
nickname: this.nickname,
|
||||
pageData: this.pageData,
|
||||
is_tourist: this.is_tourist
|
||||
}).then(res => {
|
||||
if (res.length > 0) {
|
||||
this.pageData.page++;
|
||||
}
|
||||
if (type == 'concat') {
|
||||
this.userList = this.userList.concat(res);
|
||||
} else {
|
||||
this.userList = res;
|
||||
// this.$set(this.userListTemp, this.pageData.page, res);
|
||||
}
|
||||
if (this.refresherTriggered) {
|
||||
this.refresherTriggered = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 下拉刷新被触发
|
||||
refresherrefresh() {
|
||||
if (this.refresherTriggered) {
|
||||
this.refresherTriggered = false;
|
||||
return;
|
||||
}
|
||||
if (!this.refresherTriggered) {
|
||||
this.refresherTriggered = true;
|
||||
}
|
||||
// this.refresherTriggered = true;
|
||||
this.pageData.page = 1;
|
||||
this.initData();
|
||||
},
|
||||
|
||||
// 下拉刷新复位
|
||||
refresherrestore() {
|
||||
this.refresherTriggered = false;
|
||||
},
|
||||
|
||||
//
|
||||
refresherabort() {
|
||||
this.refresherTriggered = false;
|
||||
},
|
||||
// 滑动到页面底部
|
||||
goBottom() {
|
||||
this.initData('concat');
|
||||
},
|
||||
goTop() {
|
||||
this.pageData.page = 1;
|
||||
this.initData();
|
||||
},
|
||||
updataUserCount() {
|
||||
this.$store.dispatch('updataUserCount').then(res => {
|
||||
this.scoket.setBadgeNumber(res.count);
|
||||
});
|
||||
},
|
||||
// 通过sockect连接收取新的消息
|
||||
getMssageNum(data) {
|
||||
if (data.num < 1) {
|
||||
return;
|
||||
}
|
||||
this.userList.forEach((item, index) => {
|
||||
// 如果发送方的user_id 与 列表中的 to_uid 一致
|
||||
if (item.to_user_id == data.user_id) {
|
||||
this.userList.splice(index, 1);
|
||||
}
|
||||
});
|
||||
this.userList.unshift(data.recored);
|
||||
this.updataUserCount();
|
||||
},
|
||||
// 扫描二维码
|
||||
handleScanCode() {
|
||||
// let str = "http://192.168.31.192:8081/pages/users/scan_login/index?key=463aca66113f65396dc28e3f0041a2f2";
|
||||
uni.scanCode({
|
||||
onlyFromCamera: true, // 是否只允许相机扫码,不允许相机选择图片
|
||||
success(res) {
|
||||
console.log(res);
|
||||
navigateTo(1, '/pages/view/authorizedLogin/index', {
|
||||
key: res.result.split('=')[1]
|
||||
});
|
||||
},
|
||||
fail: () => {}
|
||||
});
|
||||
},
|
||||
connentServerForUser(item) {
|
||||
item.mssage_num = 0;
|
||||
navigateTo(1, '/pages/view/customerServer/index', {
|
||||
to_user_id: item.to_user_id
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './less/messageList.less';
|
||||
</style>
|
||||
@@ -0,0 +1,305 @@
|
||||
.header {
|
||||
background: @primaryBgColor;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 15rpx;
|
||||
position: relative;
|
||||
height: 116rpx;
|
||||
&_customer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_avar {
|
||||
margin-right: 10rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
&_status {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_name {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
&_item {
|
||||
&_value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.tip_primary {
|
||||
display: inline-block;
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: linear-gradient(143deg, #27f2cb 0%, #14e3b4 100%);
|
||||
border-radius: 50%;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
.tip_danger {
|
||||
background: #f74c31 !important;
|
||||
}
|
||||
.tip_type {
|
||||
font-size: 20rpx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_handle {
|
||||
display: flex;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
align-items: center;
|
||||
.font {
|
||||
// display: inline-block;
|
||||
// width: 38rpx;
|
||||
// height: 38rpx;
|
||||
// background: rgba(255, 255, 255, 0.22);
|
||||
text-align: center;
|
||||
line-height: 38rpx;
|
||||
margin-right: 8rpx;
|
||||
font-size: 16px;
|
||||
// border-radius: 50%;
|
||||
}
|
||||
.loginOut {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
&_checkout_status {
|
||||
position: absolute;
|
||||
width: 214rpx;
|
||||
height: 173rpx;
|
||||
background: #434343;
|
||||
top: 140rpx;
|
||||
left: 43rpx;
|
||||
z-index: 90;
|
||||
border-radius: 10px;
|
||||
&_sanjiao {
|
||||
background: #434343;
|
||||
position: absolute;
|
||||
top: -15rpx;
|
||||
left: 30rpx;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&_select {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
|
||||
&_item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #fff;
|
||||
padding: 0 30rpx;
|
||||
border-bottom: 1px solid #fff;
|
||||
&_tip {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(180deg, #bcbcbc 0%, #919191 100%);
|
||||
}
|
||||
.tip_select {
|
||||
background: linear-gradient(143deg, #27f2cb 0%, #14e3b4 100%);
|
||||
}
|
||||
.tip_select_outline {
|
||||
background: #f74c31;
|
||||
}
|
||||
&_status {
|
||||
flex: 1;
|
||||
padding-left: 15rpx;
|
||||
font-size: 14px;
|
||||
}
|
||||
&_icon {
|
||||
color: #b9b9b9;
|
||||
}
|
||||
}
|
||||
&_line {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background: #f0f1f2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 内容部分样式
|
||||
.content {
|
||||
&_search {
|
||||
padding: 20rpx 30rpx;
|
||||
border-bottom: 1px solid #eceff8;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_box {
|
||||
flex: 1;
|
||||
// margin-right: 20rpx;
|
||||
display: flex;
|
||||
padding: 14rpx 22rpx;
|
||||
background: #f5f6f9;
|
||||
border-radius: 39rpx;
|
||||
.icon {
|
||||
margin-right: 12rpx;
|
||||
color: #c4c4c4;
|
||||
}
|
||||
.input {
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.reload {
|
||||
}
|
||||
}
|
||||
|
||||
// 聊天内容
|
||||
&_userMessgae {
|
||||
padding: 0 30rpx;
|
||||
background: #fff;
|
||||
&_item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 28rpx 0;
|
||||
border-bottom: 1px solid #f6f6f6;
|
||||
transition: transform 0.3s;
|
||||
&_avar {
|
||||
border-radius: 50%;
|
||||
// overflow: hidden;
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
margin-right: 22rpx;
|
||||
// border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
// background: @primaryBgColor;
|
||||
position: relative;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.online_status {
|
||||
position: absolute;
|
||||
right: 0rpx;
|
||||
bottom: 0rpx;
|
||||
z-index: 10;
|
||||
display: inline-block;
|
||||
width: 15rpx;
|
||||
height: 15rpx;
|
||||
background: #ccc;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.off {
|
||||
background: linear-gradient(143deg, #27f2cb 0%, #14e3b4 100%);
|
||||
}
|
||||
}
|
||||
|
||||
&_value {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
overflow: hidden;
|
||||
padding-top: 8rpx;
|
||||
&_user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_nickName {
|
||||
font-size: 14px;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
font-weight: 600;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
&_form {
|
||||
font-size: 26rpx;
|
||||
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
.wchat {
|
||||
background: rgba(56, 117, 234, 0.14);
|
||||
color: rgba(56, 117, 234, 1);
|
||||
}
|
||||
.h5 {
|
||||
background: rgba(255, 162, 0, 0.18);
|
||||
color: #d08800;
|
||||
}
|
||||
.gozhonghao {
|
||||
background: rgba(0, 186, 100, 0.14);
|
||||
color: #00a219;
|
||||
}
|
||||
.pc {
|
||||
color: #820adb;
|
||||
background: rgba(133, 64, 227, 0.14);
|
||||
}
|
||||
}
|
||||
|
||||
// 用户消息
|
||||
&_message {
|
||||
color: rgba(159, 159, 159, 1);
|
||||
font-size: 24rpx;
|
||||
width: 100%;
|
||||
.overText;
|
||||
}
|
||||
}
|
||||
|
||||
// 聊天时间
|
||||
&_createTime {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-top: 8rpx;
|
||||
&_value {
|
||||
color: rgba(159, 159, 159, 1);
|
||||
font-size: 22rpx;
|
||||
}
|
||||
&_count {
|
||||
align-self: flex-end;
|
||||
display: inline-block;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
line-height: 38rpx;
|
||||
text-align: center;
|
||||
background: rgba(247, 76, 49, 1);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
&_del {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -30rpx;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100rpx;
|
||||
background-color: rgba(255, 0, 0, 1);
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
transform: translateX(100%);
|
||||
}
|
||||
&.on {
|
||||
transform: translateX(-100rpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.no_message {
|
||||
text-align: center;
|
||||
padding: 60rpx 0;
|
||||
font-size: 14px;
|
||||
color: #ccc;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<view class="agreement">
|
||||
<view class="content" v-html="agreement"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from 'pages/api/api.js';
|
||||
import http from 'pages/api/index';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
agreement: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getAgreement();
|
||||
},
|
||||
methods: {
|
||||
getAgreement() {
|
||||
http(api.userAgreement, {}).then(res => {
|
||||
console.log(res);
|
||||
this.agreement = res.content;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.agreement .content {
|
||||
margin: 10rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
|
||||
|
||||
<div slot="content">
|
||||
<div class="content">
|
||||
<div class="content_tag"><span>标签名称</span></div>
|
||||
<!-- <div class="content_input"><input type="text" placeholder="请输入标签名称" /></div> -->
|
||||
<div class="content_input">
|
||||
<span>{{ tagsData.label }}</span>
|
||||
</div>
|
||||
<div class="content_tag"><span>标签成员</span></div>
|
||||
<div class="content_group">
|
||||
<!-- <div class="content_group_handle">
|
||||
<span class="iconfont"></span>
|
||||
<span>添加成员</span>
|
||||
</div> -->
|
||||
<view class="user-content">
|
||||
<view class="user-list" v-for="item in canEachUserList" :key="item.key">
|
||||
<div class="content_tag">
|
||||
<span>{{ item.key }}</span>
|
||||
</div>
|
||||
<uni-swipe-action v-for="items in item.list" :key="items.id">
|
||||
<uni-swipe-action-item>
|
||||
<view class="user" @click="toUserMessage(items)">
|
||||
<view class="user-list-left"><image :src="items.avatar" mode=""></image></view>
|
||||
<view class="user-list-right">{{ items.nickname }}</view>
|
||||
</view>
|
||||
|
||||
<template v-slot:right>
|
||||
<div class="delete_tags" @click="deleteUser(items)"><text>删除</text></div>
|
||||
</template>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { navigateTo, navigateBack, Modal, Toast } from 'pages/utils/uniApi.js';
|
||||
import { makePy } from 'pages/utils/utils';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userList: [],
|
||||
canEachUserList: [],
|
||||
tagsData: {}
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.tagsData = this.$cache.get('userTagData');
|
||||
this.canEachUserList = this.letterSrot(this.tagsData.user);
|
||||
},
|
||||
methods: {
|
||||
// 前往用户详情界面
|
||||
toUserMessage(item) {
|
||||
navigateTo(1, '/pages/view/customerServer/customerMessage', { ...item, user_id: item.id });
|
||||
},
|
||||
// 删除用户
|
||||
deleteUser(item) {
|
||||
Modal('温馨提示', `"${item.nickname}"将被删除,请问是否继续?`).then(() => {
|
||||
http(api.deleteUserLabel, {
|
||||
userId: item.id,
|
||||
labelId: this.tagsData.id
|
||||
}).then(res => {
|
||||
this.canEachUserList.forEach(key => {
|
||||
key.list.forEach((val, index, arr) => {
|
||||
if (item.id == val.id) {
|
||||
arr.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
Toast('删除成功');
|
||||
});
|
||||
});
|
||||
},
|
||||
cencel() {
|
||||
navigateBack(1);
|
||||
},
|
||||
// 对通讯录按字母顺序做排序
|
||||
letterSrot(userList) {
|
||||
const sortList = [];
|
||||
const list = userList;
|
||||
const letter = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||
letter.forEach(item => {
|
||||
const obj = {};
|
||||
obj.key = item;
|
||||
obj.list = [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (item == makePy(list[i].nickname).substr(0, 1)) {
|
||||
obj.list.push(list[i]);
|
||||
list.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (obj.list.length) sortList.push(obj);
|
||||
});
|
||||
return sortList;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import url('./less/addTag.less');
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 96rpx;
|
||||
padding: 0 30rpx;
|
||||
font-size: 16px;
|
||||
&_title {
|
||||
font-weight: 600;
|
||||
}
|
||||
.finish {
|
||||
width: 92rpx;
|
||||
height: 56rpx;
|
||||
background: #dddddd;
|
||||
opacity: 1;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #aaaaaa;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<div slot="content" class="content">
|
||||
<!-- <div class="handle_title" @click="createdTag">
|
||||
<span class="iconfont"></span>
|
||||
<span class="handle_title_message">新建标签</span>
|
||||
</div> -->
|
||||
|
||||
<!-- <uni-swipe-action>
|
||||
<uni-swipe-action-item>
|
||||
<div class="tag_container">
|
||||
<div class="tag_container_name">
|
||||
<span class="name">意向客户</span>
|
||||
<span class="num">(9)</span>
|
||||
</div>
|
||||
<div class="tag_container_user">
|
||||
<div class="userList">
|
||||
阿萨大大啊水水水水水水水水水水水水水水水水水水水啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊反反复复反反复复反反复复方法方法分分分3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-slot:right>
|
||||
<div class="delete_tags">
|
||||
<text>删除</text>
|
||||
</div>
|
||||
</template>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action> -->
|
||||
|
||||
<div class="tag_container" v-for="(item, index) in tagList" :key="index" @click="toTagDetils(item)">
|
||||
<div class="tag_container_name">
|
||||
<span class="name">{{item.label}}</span>
|
||||
<span class="num" v-if="item.user.length">({{ item.user.length }})</span>
|
||||
</div>
|
||||
<div class="tag_container_user">
|
||||
<div class="userList" v-if="item.user.length">
|
||||
{{item.user.map(item=> item.nickname).join(',')}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { navigateTo} from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userData: {},
|
||||
tagList: []
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.userData = opt;
|
||||
},
|
||||
onShow() {
|
||||
this.initData();
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
http(api.userLabe, { id: this.userData.user_id }).then(res => {
|
||||
console.log(res);
|
||||
this.tagList = res;
|
||||
})
|
||||
},
|
||||
toTagDetils(item) {
|
||||
this.$cache.get('userTagData', item);
|
||||
navigateTo(1, '/pages/view/setTags/addTag');
|
||||
|
||||
},
|
||||
createdTag() {
|
||||
navigateTo(1, '/pages/view/setTags/addTag');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('./less/setTags.less');
|
||||
</style>
|
||||
@@ -0,0 +1,63 @@
|
||||
@padding-l-r:30rpx;
|
||||
@padding-t-p:20rpx;
|
||||
@bgc-f:#FFFFFF;
|
||||
@fontSize:28rpx;
|
||||
@imgSize:64rpx;
|
||||
.content_tag {
|
||||
padding: 14rpx 30rpx;
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
background: #eeeeee;
|
||||
}
|
||||
.content_input {
|
||||
padding: 24rpx 30rpx;
|
||||
input {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.content_group {
|
||||
&_handle {
|
||||
color: #3875EA;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #F0F2F7;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
}
|
||||
.user-content{
|
||||
background-color: #EEEEEE;
|
||||
.user-list{
|
||||
.number{
|
||||
color: #666666;
|
||||
font-size:@fontSize - 2rpx;
|
||||
}
|
||||
.user{
|
||||
background-color: @bgc-f;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding:30rpx 28rpx;
|
||||
border-bottom: 1rpx solid #F0F2F7;
|
||||
.user-list-left{
|
||||
width: @imgSize;
|
||||
height: @imgSize;
|
||||
padding-right: 20rpx;
|
||||
image{
|
||||
width: @imgSize;
|
||||
height: @imgSize;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.user-list-right{
|
||||
color: #282828;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete_tags {
|
||||
padding: 27rpx 37rpx;
|
||||
background: #F74C31;
|
||||
color: #fff;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
.bg {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f0f2f7;
|
||||
}
|
||||
.handle_title {
|
||||
color: @primaryColor;
|
||||
padding: 35rpx 30rpx;
|
||||
.bg;
|
||||
}
|
||||
|
||||
.tag_container {
|
||||
.bg;
|
||||
padding: 15rpx 30rpx;
|
||||
font-size: 15px;
|
||||
&_name {
|
||||
color: #282828;
|
||||
font-weight: 600;
|
||||
}
|
||||
&_user {
|
||||
color: #999999;
|
||||
margin-top: 6rpx;
|
||||
.userList {
|
||||
.overText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete_tags {
|
||||
padding: 39rpx;
|
||||
background: #F74C31;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<!-- <div slot="header" class="header">
|
||||
<div class="title_name">统计</div>
|
||||
|
||||
</div> -->
|
||||
<div slot="content">
|
||||
<div class="statistics"></div>
|
||||
<div class="statistics_list">
|
||||
<div class="statistics_list_item">
|
||||
<div class="statistics_list_item_value">{{ statisticsAll.all }}</div>
|
||||
<div class="statistics_list_item_label">全部客户</div>
|
||||
</div>
|
||||
<div class="statistics_list_item">
|
||||
<div class="statistics_list_item_value">{{ statisticsAll.toDayKefu }}</div>
|
||||
<div class="statistics_list_item_label">今日客户</div>
|
||||
</div>
|
||||
<div class="statistics_list_item">
|
||||
<div class="statistics_list_item_value">{{ statisticsAll.month }}</div>
|
||||
<div class="statistics_list_item_label">本月客户</div>
|
||||
</div>
|
||||
<div class="statistics_list_item">
|
||||
<div class="statistics_list_item_value">{{ statisticsAll.toDayTourist }}</div>
|
||||
<div class="statistics_list_item_label">今日游客</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content_charts">
|
||||
<div class="content_charts_title">
|
||||
<div class="content_charts_title_select">
|
||||
<scroll-view scroll-x class="content_charts_title_select_scroll">
|
||||
<view class="scroll_content">
|
||||
<view class="scroll_content_item" v-for="(item, index) in monthList" :key="index" @click="handleSelectMonth(item)">
|
||||
<div class="scroll_content_item_label" :class="{ selectEd: selectMonth == item.value }">{{ item.label }}</div>
|
||||
<div class="tip" v-if="selectMonth == item.value"></div>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</div>
|
||||
|
||||
<div class="content_charts_title_date">
|
||||
<biaofun-datetime-picker
|
||||
class="positionPicker"
|
||||
:class="{ primaryColor: searchChartsData.value }"
|
||||
placeholder="请选择年月"
|
||||
:defaultValue="searchChartsData.value"
|
||||
start="2000"
|
||||
end="2100"
|
||||
fields="month"
|
||||
@change="changeDatetimePicker"
|
||||
:key="searchChartsData.value"
|
||||
></biaofun-datetime-picker>
|
||||
<!-- <span>{{searchChartsData.value}}</span> -->
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content_charts_value">
|
||||
<view class="charts-box">
|
||||
<div class="title">新增(人)</div>
|
||||
<qiun-data-charts type="area" :inScrollView="true" canvasId="scrolllineid" :opts="opts" :chartData="chartData" :ontouch="true" :canvas2d="true" />
|
||||
</view>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import biaofunDatetimePicker from '@/components/biaofun-datetime-picker/biaofun-datetime-picker.vue';
|
||||
import { formatDate } from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
export default {
|
||||
components: {
|
||||
biaofunDatetimePicker
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectMonth: 'yesterday',
|
||||
chartData: {
|
||||
categories: [],
|
||||
series: [
|
||||
{
|
||||
name: '客户',
|
||||
data: [],
|
||||
color: '#3875EA',
|
||||
legendShape: 'square' // 长方形
|
||||
},
|
||||
{
|
||||
name: '游客',
|
||||
data: [],
|
||||
color: '#3FC7A9',
|
||||
legendShape: 'square'
|
||||
}
|
||||
]
|
||||
},
|
||||
opts: {
|
||||
enableScroll: true,
|
||||
extra: {
|
||||
area: { type: 'curve', addLine: true, gradient: true }
|
||||
},
|
||||
xAxis: {
|
||||
type: 'grid',
|
||||
gridType: 'solid',
|
||||
itemCount: 5, //x轴单屏显示数据的数量,默认为5个
|
||||
scrollShow: false, //新增是否显示滚动条,默认false
|
||||
scrollAlign: 'left', //滚动条初始位置
|
||||
scrollBackgroundColor: '#F7F7FF', //默认为 #EFEBEF
|
||||
scrollColor: '#DEE7F7' //默认为 #A6A6A6
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
float: 'right',
|
||||
padding: 2,
|
||||
margin: 20,
|
||||
backgroundColor: 'rgba(0,0,0,0)',
|
||||
borderColor: 'rgba(0,0,0,0)',
|
||||
borderWidth: 0,
|
||||
fontSize: 13,
|
||||
fontColor: '#666666',
|
||||
lineHeight: 11,
|
||||
hiddenColor: '#CECECE',
|
||||
itemGap: 10
|
||||
}
|
||||
},
|
||||
statisticsAll: {}, // 客户总统计数据
|
||||
searchChartsData: {
|
||||
year: String(new Date().getFullYear() + '-' + new Date().getMonth() + 1),
|
||||
month: new Date().getMonth() + 1,
|
||||
value: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
monthList() {
|
||||
let arr = [
|
||||
{
|
||||
label: '昨天',
|
||||
value: 'yesterday'
|
||||
},
|
||||
{
|
||||
label: '今天',
|
||||
value: 'today'
|
||||
},
|
||||
{
|
||||
label: '7天',
|
||||
value: 'lately7'
|
||||
},
|
||||
{
|
||||
label: '30天',
|
||||
value: 'lately30'
|
||||
},
|
||||
{
|
||||
label: '半年',
|
||||
value: 'lately180'
|
||||
}
|
||||
];
|
||||
// for (let i = 1; i < new Date().getMonth(); i++) {
|
||||
// arr.push({
|
||||
// month: i,
|
||||
// label: i + '月'
|
||||
// });
|
||||
// }
|
||||
// let monthArr = [
|
||||
// {
|
||||
// label: '当月',
|
||||
// month: new Date().getMonth() + 1
|
||||
// },
|
||||
// {
|
||||
// label: '上月',
|
||||
// month: new Date().getMonth()
|
||||
// }
|
||||
// ];
|
||||
// arr.push(...monthArr);
|
||||
// arr.reverse();
|
||||
|
||||
return arr;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// searchChartsData: {
|
||||
// handler() {
|
||||
// this.getChartsData();
|
||||
// },
|
||||
// deep: true,
|
||||
// immediate: true
|
||||
// }
|
||||
},
|
||||
onShow() {
|
||||
// this.searchChartsData.value = formatDate(new Date().getTime(), 'yyyy-MM');
|
||||
// this.selectMonth = this.searchChartsData.month; // 自动选择本月
|
||||
this.initData();
|
||||
this.getChartsData();
|
||||
},
|
||||
methods: {
|
||||
// 获取数据总统计
|
||||
initData() {
|
||||
http(api.statisticsAll, {}).then(res => {
|
||||
this.statisticsAll = res;
|
||||
});
|
||||
},
|
||||
// 获取图标统计数据
|
||||
getChartsData() {
|
||||
let categories = [];
|
||||
http(api.statisticsIndex, { time: this.selectMonth }).then(res => {
|
||||
// 构建 X 轴数据
|
||||
// 将两条年份数据拼合在一起, 给对应的条目赋值
|
||||
// if (res.list.length) {
|
||||
res.list.forEach(item => {
|
||||
categories.push(item.time);
|
||||
});
|
||||
this.chartData.series[0].data = res.list.map(item => item.number);
|
||||
// }
|
||||
|
||||
// if (res.tourist.length) {
|
||||
res.tourist.forEach(item => {
|
||||
categories.push(item.time);
|
||||
});
|
||||
this.chartData.series[1].data = res.tourist.map(item => item.number);
|
||||
// }
|
||||
// 数组去重
|
||||
categories = Array.from(new Set(categories));
|
||||
// 数组从小到大排序
|
||||
categories.sort((val1, val2) => {
|
||||
return Number(val1.replace(/-/g, '')) - Number(val2.replace(/-/g, ''));
|
||||
});
|
||||
|
||||
this.chartData.categories = categories;
|
||||
});
|
||||
},
|
||||
// 选择年份
|
||||
changeDatetimePicker(e) {
|
||||
this.searchChartsData.value = formatDate(e.dt, 'yyyy/MM');
|
||||
this.selectMonth = this.searchChartsData.value;
|
||||
this.getChartsData();
|
||||
},
|
||||
// 选择月份
|
||||
handleSelectMonth(item) {
|
||||
this.selectMonth = item.value;
|
||||
this.searchChartsData.value = '';
|
||||
this.getChartsData();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import url('./less/statistics.less');
|
||||
</style>
|
||||
@@ -0,0 +1,141 @@
|
||||
.header {
|
||||
height: 201rpx;
|
||||
background: @primaryBgColor;
|
||||
.title_name {
|
||||
text-align: center;
|
||||
padding: 20rpx;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.statistics {
|
||||
background: #1890FC;
|
||||
padding: 43rpx 30rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.statistics_list {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 690rpx;
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
padding: 43rpx 30rpx;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
&_item {
|
||||
&_value {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
&_label {
|
||||
color: #999999;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding-top: 36.2rpx;
|
||||
&_charts {
|
||||
width: 690rpx;
|
||||
// padding: 34rpx 26rpx;
|
||||
|
||||
box-sizing: border-box;
|
||||
margin: auto;
|
||||
background: #fff;
|
||||
// border-radius: 12px;
|
||||
// overflow: hidden;
|
||||
&_title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 34rpx 26rpx;
|
||||
padding-bottom: 0;
|
||||
&_select {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
&_scroll {
|
||||
.scroll_content {
|
||||
display: flex;
|
||||
// width: 100%;
|
||||
justify-content: space-around;
|
||||
&_item {
|
||||
// margin-right: 52rpx;
|
||||
&_label {
|
||||
font-size: 15px;
|
||||
white-space: nowrap;
|
||||
color: #999999;
|
||||
text-align: center;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
.selectEd {
|
||||
color: @primaryColor;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tip {
|
||||
width: 40rpx;
|
||||
height: 4rpx;
|
||||
background: #3875ea;
|
||||
opacity: 1;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.content_charts_title_date {
|
||||
// width: 110rpx;
|
||||
// height: 110rpx;
|
||||
background: #ffffff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 30rpx;
|
||||
// white-space: nowrap;
|
||||
// position: relative;
|
||||
.positionPicker {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&_value {
|
||||
.charts-box {
|
||||
position: relative;
|
||||
.title {
|
||||
position: absolute;
|
||||
top: 70rpx;
|
||||
left: 30rpx;
|
||||
font-size: 11px;
|
||||
color: #cccccc;
|
||||
z-index: 999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.content_charts_title_date:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background: #000000;
|
||||
opacity: 0.08;
|
||||
}
|
||||
.primaryColor {
|
||||
color: @primaryColor;
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out>
|
||||
<div slot="content">
|
||||
<div class="header"></div>
|
||||
<div class="box">
|
||||
<div class="img" @click="setting">
|
||||
<image :src="customerServerData.avatar" mode=""></image>
|
||||
</div>
|
||||
<div>
|
||||
<div class="box_font1">
|
||||
<span>{{ customerServerData.nickname }}</span>
|
||||
<span class="isOnline" :class="{ online: customerServerData.online == '1' }"
|
||||
@click="handleChangeOnline">
|
||||
<span></span>
|
||||
<span>{{ customerServerData.online == '1' ? '在线' : '离线' }}</span>
|
||||
|
||||
<!-- 切换上线下线弹框开始 -->
|
||||
<span class="onLineModel" v-if="onlineModel">
|
||||
<span class="sanjiao"></span>
|
||||
<span class="model_text" @click="online(1)">
|
||||
<span class="dian online"></span>
|
||||
<span>在线</span>
|
||||
<span class="iconfont"
|
||||
:class="{ opacity0: !(customerServerData.online == '1') }"></span>
|
||||
</span>
|
||||
<span class="xian"></span>
|
||||
<span class="model_text" @click="online(0)">
|
||||
<span class="dian"></span>
|
||||
<span>离线</span>
|
||||
<span class="iconfont"
|
||||
:class="{ opacity0: !(!customerServerData.online || customerServerData.online == '0') }"></span>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- 切换上线下线弹框结束 -->
|
||||
</span>
|
||||
</div>
|
||||
<div class="box_font2">手机号:{{ customerServerData.phone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content_box" @click="setting">
|
||||
<div class="icon"><span class="iconfont iconPrimaryColor"></span></div>
|
||||
<div class="text">个人信息</div>
|
||||
<div>
|
||||
<image src="~static/images/right.png" alt=""></image>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="content_box" @click="authReply">
|
||||
<div class="icon"><span class="iconfont iconPrimaryColor"></span></div>
|
||||
<div class="text">自动回复</div>
|
||||
<div>
|
||||
<image src="~static/images/right.png" alt=""></image>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line"></div>
|
||||
<div class="content_box" @click="feedback">
|
||||
<div class="icon"><span class="iconfont iconPrimaryColor"></span></div>
|
||||
<div class="text">意见反馈</div>
|
||||
<div>
|
||||
<image src="~static/images/right.png" alt=""></image>
|
||||
</div>
|
||||
</div>
|
||||
<div class="line" v-if='isDomainName'></div>
|
||||
<div class="content_box" v-if='isDomainName' @click="editDominName">
|
||||
<div class="icon"><span class="iconfont iconPrimaryColor"></span></div>
|
||||
<div class="text">域名设置</div>
|
||||
<div class="message">
|
||||
<span>{{ dominName }}</span>
|
||||
<image src="~static/images/right.png" alt=""></image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="content_box" @click="loginOut">
|
||||
<div class="icon"><span class="iconfont iconPrimaryColor"></span></div>
|
||||
<div class="text">退出登录</div>
|
||||
<div>
|
||||
<image src="~static/images/right.png" alt=""></image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="copyright"><span class="iconfont"></span></div>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
navigateTo,
|
||||
Modal
|
||||
} from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import config from 'pages/config/app.js';
|
||||
export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
customerServerData: {},
|
||||
dominName: '',
|
||||
use: false,
|
||||
onlineModel: false,
|
||||
isDomainName: config.isDomainName
|
||||
};
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.dominName = this.$cache.get('dominName');
|
||||
this.customerServerData = this.$store.getters.kefuInfo;
|
||||
},
|
||||
onShow() {
|
||||
this.initData();
|
||||
},
|
||||
onHide() {
|
||||
this.onlineModel = false;
|
||||
},
|
||||
onUnload() {
|
||||
this.onlineModel = false;
|
||||
},
|
||||
methods: {
|
||||
// 获取当前登录客服信息
|
||||
initData() {
|
||||
this.$store.dispatch('getKeufuInfo').then(res => {
|
||||
this.customerServerData = res;
|
||||
});
|
||||
},
|
||||
// 意见反馈
|
||||
feedback() {
|
||||
navigateTo(1, '/pages/view/feedback/index');
|
||||
},
|
||||
authReply() {
|
||||
navigateTo(1, '/pages/view/authReply/index');
|
||||
},
|
||||
// 设置
|
||||
setting() {
|
||||
navigateTo(1, '/pages/view/user/setting/setting', this.customerServerData);
|
||||
},
|
||||
// 修改域名
|
||||
editDominName() {
|
||||
navigateTo(1, '/pages/view/dominName/index');
|
||||
},
|
||||
// 退出登录
|
||||
loginOut() {
|
||||
Modal('温馨提示', '您确定要退出登录吗?').then(() => {
|
||||
http(api.userLogout)
|
||||
.then(res => {
|
||||
//关闭长连接
|
||||
this.scoket.clearPing();
|
||||
this.$store.commit('clearChat');
|
||||
this.$store.commit('logout');
|
||||
navigateTo(3, '/pages/view/login/index');
|
||||
})
|
||||
.catch(res => {
|
||||
this.scoket.clearPing();
|
||||
this.$store.commit('clearChat');
|
||||
this.$store.commit('logout');
|
||||
navigateTo(3, '/pages/view/login/index');
|
||||
});
|
||||
});
|
||||
},
|
||||
// 更改在线状态
|
||||
handleChangeOnline() {
|
||||
this.onlineModel = !this.onlineModel;
|
||||
},
|
||||
online(val) {
|
||||
this.scoket.send({
|
||||
data: {
|
||||
online: val
|
||||
},
|
||||
type: 'online'
|
||||
});
|
||||
this.customerServerData.online = val;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.header {
|
||||
background: #1890fc;
|
||||
padding: 43rpx 30rpx;
|
||||
// height: 83rpx;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 690rpx;
|
||||
height: 180rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
|
||||
image {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin-left: 34rpx;
|
||||
margin-right: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.box_font1 {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
line-height: 42rpx;
|
||||
color: #282828;
|
||||
margin-bottom: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.box_font2 {
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
line-height: 37rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 690rpx;
|
||||
margin: 0 auto;
|
||||
margin-top: 40rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
|
||||
.line {
|
||||
width: 90%;
|
||||
height: 1px;
|
||||
background: #eeeeee;
|
||||
position: relative;
|
||||
left: 10%;
|
||||
}
|
||||
|
||||
.content_box {
|
||||
padding: 28rpx 30rpx;
|
||||
// height: 88rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
// margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1;
|
||||
// width: 84%;
|
||||
}
|
||||
|
||||
image {
|
||||
width: 33rpx;
|
||||
height: 33rpx;
|
||||
}
|
||||
|
||||
.message {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 300rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 250rpx;
|
||||
color: #cccccc;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.iconPrimaryColor {
|
||||
// color: @primaryColor;
|
||||
}
|
||||
|
||||
.isOnline {
|
||||
width: 100rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 18rpx;
|
||||
background: #999999;
|
||||
display: flex;
|
||||
margin-left: 9rpx;
|
||||
color: #fff;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-size: 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.isOnline>span:nth-child(1) {}
|
||||
|
||||
.dian {
|
||||
display: inline-block;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 50%;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.online {
|
||||
background: #20c93b;
|
||||
}
|
||||
|
||||
.onLineModel {
|
||||
position: absolute;
|
||||
top: 50rpx;
|
||||
left: 43rpx;
|
||||
z-index: 999 !important;
|
||||
background: #434343;
|
||||
border-radius: 6px;
|
||||
width: 180rpx;
|
||||
height: 150rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.sanjiao {
|
||||
background: #434343;
|
||||
position: absolute;
|
||||
top: -15rpx;
|
||||
left: 30rpx;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.model_text {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30rpx;
|
||||
white-space: nowrap;
|
||||
font-size: 24rpx;
|
||||
|
||||
.dian {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.xian {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #f0f1f2;
|
||||
}
|
||||
|
||||
.opacity0 {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.onlineFlag {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,342 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<lay-out titleName="设置">
|
||||
<div slot="content">
|
||||
<view class='personal-data'>
|
||||
<view class='list'>
|
||||
<view class='item'>
|
||||
<view>头像</view>
|
||||
<view class="avatar-box" @click='uploadpic'>
|
||||
<image :src="customerServerData.avatar"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class='item'>
|
||||
<view>昵称</view>
|
||||
<view class='input'><input v-model="customerServerData.nickname" type='text' placeholder="请输入客服名称"></input></view>
|
||||
</view>
|
||||
<view class='item'>
|
||||
<view>手机号</view>
|
||||
<view class='input'>
|
||||
<view class='input'><input v-model="customerServerData.phone" type='number' placeholder="请填写联系方式"></input></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view>密码</view>
|
||||
<view class='input'>
|
||||
<view class='input'><input v-model="customerServerData.password" type='number' placeholder="请输入密码"></input></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</div>
|
||||
</lay-out>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { navigateTo, chooseImage, pathToBase64 , Toast, Modal, Loading, hideLoading} from 'pages/utils/uniApi.js';
|
||||
import http from 'pages/api/index';
|
||||
import api from 'pages/api/api.js';
|
||||
import { mapState } from 'vuex'
|
||||
const app = getApp()
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dominName: '',
|
||||
customerServerData: {}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
...mapState(['token'])
|
||||
},
|
||||
onLoad(opt) {
|
||||
this.initData()
|
||||
this.dominName = this.$cache.get('dominName');
|
||||
},
|
||||
onNavigationBarButtonTap() {
|
||||
this.handleEdit();
|
||||
},
|
||||
methods: {
|
||||
edit(){
|
||||
uni.navigateTo({
|
||||
url:'/pages/view/example'
|
||||
})
|
||||
},
|
||||
// 修改域名
|
||||
editDominName() {
|
||||
navigateTo(3, '/pages/view/dominName/index');
|
||||
},
|
||||
// 获取当前登录客服信息
|
||||
initData() {
|
||||
http(api.userUserInfo).then(res => {
|
||||
this.customerServerData = res;
|
||||
console.log(this.customerServerData);
|
||||
});
|
||||
},
|
||||
// 发送图片
|
||||
uploadpic() {
|
||||
let that = this;
|
||||
chooseImage(1).then(res => {
|
||||
//#ifndef H5
|
||||
uni.compressImage({
|
||||
src: res.tempFilePaths[0],
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
success(res) {
|
||||
console.log('ok');
|
||||
that.upload(res.tempFilePath);
|
||||
},
|
||||
fail(e) {
|
||||
console.log(e,'error');
|
||||
that.upload(res.tempFilePaths[0]);
|
||||
}
|
||||
});
|
||||
//#endif
|
||||
//#ifdef H5
|
||||
that.upload(res.tempFilePaths[0]);
|
||||
//#endif
|
||||
});
|
||||
},
|
||||
upload(tempFilePath) {
|
||||
uni.uploadFile({
|
||||
url: app.globalData.http + api.kefuUploadAvatar.url,
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
// file: res.tempFilePaths[0],
|
||||
filename: 'file'
|
||||
},
|
||||
header: {
|
||||
// #ifdef MP || APP-PLUS
|
||||
'Content-Type': 'multipart/form-data',
|
||||
// #endif
|
||||
'Authori-zation': 'Bearer ' + this.token
|
||||
},
|
||||
success: uploadFileRes => {
|
||||
console.log(uploadFileRes)
|
||||
let unloadResponse = JSON.parse(uploadFileRes.data);
|
||||
if (unloadResponse.status == 200) {
|
||||
this.customerServerData.avatar = unloadResponse.data.url;
|
||||
}
|
||||
},
|
||||
fail: res => {
|
||||
Toast('上传图片失败');
|
||||
},
|
||||
complete: res => {
|
||||
console.log(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 确定修改
|
||||
handleEdit() {
|
||||
|
||||
let postData = this.customerServerData;
|
||||
if(!postData.password) {
|
||||
postData.password = '******'
|
||||
}
|
||||
http(api.putKefuUserUserInfo, postData).then(res => {
|
||||
Toast('修改成功');
|
||||
this.initData();
|
||||
})
|
||||
},
|
||||
// 退出登录
|
||||
loginOut() {
|
||||
http(api.userLogout).then(res => {
|
||||
Modal('温馨提示', '您确定要退出登录吗?').then(() => {
|
||||
navigateTo(3, '/pages/view/login/index');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.personal-data {
|
||||
background-color: #fff;
|
||||
// padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.personal-data .title {
|
||||
margin-bottom: 30rpx;
|
||||
font-size: 32rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item {
|
||||
width: 690rpx;
|
||||
height: 160rpx;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 22rpx;
|
||||
padding: 0 30rpx;
|
||||
position: relative;
|
||||
border: 2rpx solid #f8f8f8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item.on {
|
||||
border-color: #e93323;
|
||||
border-radius: 20rpx;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAArIAAACgCAYAAADw+I85AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0QzNkY3NzlCNzJCMTFFOTgyNEU4QzhGQTRFRUY2REQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0QzNkY3N0FCNzJCMTFFOTgyNEU4QzhGQTRFRUY2REQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozRDM2Rjc3N0I3MkIxMUU5ODI0RThDOEZBNEVFRjZERCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozRDM2Rjc3OEI3MkIxMUU5ODI0RThDOEZBNEVFRjZERCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pn3rJMAAAArUSURBVHja7N3NXuLIGsDhqigK2Ou+grmEuf/t2fT+bOYKZn9aW5Q6qaQSIoKfoCQ8z29QRBSBzX+q31RiSikAAMDYVF4CAACELAAACFkAABCyAAAIWQAAELIAACBkAQAQsgAAIGQBAEDIAgCAkAUAQMgCAICQBQAAIQsAgJAFAAAhCwAAQhYAACELAABCFgAAhCwAAAhZAACELAAACFkAABCyAAAIWQAAELIAACBkAQAQsgAAIGQBAEDIAgCAkAUAQMgCAICQBQAAIQsAgJAFAAAhCwAAQhYAACELAABCFgAAhCwAAAhZAACELAAACFkAABCyAAAIWQAAELIAACBkAQAQsgAAIGQBAEDIAgCAkAUAQMgCAICQBQAAIQsAgJAFAAAhCwAAQhYAACELAABCFgAAhCwAAAhZAACELAAACFkAABCyAAAIWQAAELIAACBkAQBAyAIAIGQBAEDIAgCAkAUAQMgCAMAJuPQSAABMy79///XaXfJi5qy0YFUuqVzW9eWhvqzK9b1+/vpHyAIAcMjCqxs1tldj/zHl/6oU4rz+ctY2a3tzjO2n0F6tUqobMYZ5fX1V337XBm0MMbX3SuXnvv1peqcBAKYlXl+VSI2lZJuIzSuwi7pUY3/HFPsijYMPcVOps9hG7W19fRVT+50YT6TXvdUAABML2at5V6rdTdfNSmzXquX2FOKTr7trsVvBjeVOISzLyuyfNnNTOIWWFbIAAFNzfd2umjYrsmlWR+i8KuusXbhurudZgTZpU6w/p82Ka0oldJvb47z+cp3HDU5kQVbIAgBMTVwsmzitr1V1ni5C07Pd5EAXtCVlm3BNTfS27dvGbAiDcYPUr9TWvys91jetT2BEVsgCAEwuZOeLJkDr/+Z5sbXdb7UdCIixb9M2WDdjss2n4X274YN2LraJ3fzjeUTh9yk8TyELADC1kM0rsjHVTRpnTYam2I8LNBOuaRO0TbaWbQhidyRYKveLmz0P+vu223ZV8ZWtuYQsAADvD9nlTTMb23/dxelg9TUM4nSzRLvZsSANf274u9uvZnXm/hGyAAAcVHWzzKusl5uDtvq9YtvvpzZJmwGC+GS1tR83iHuGYMuPXtbfF7IAABxWXP7IyVkNT4awGQ/Y7FswHBkIW9e7W1Kfv0/GDKpTeJ5CFgBgapbLPAJQxX5X2DIuEPsdYtsSTak/nKv5Xir7GQxWZNvvlZGC/pReUcgCAHB41c2PnbfHrc+v3bbv61MhZAEAJibmkE1pXRdo9SRDuxXVuJWp3XBsGYDdfL9frx38jub767LVgZAFAOCAIdvsWpBjs5tlHZx4tvmQNhsVdH1bAjYO9pTtrlX9cEJvfQrPU8gCAExMdXOTPz3knQvCk/1iU4iDhO3HCuKT8yK0v6P/mfL9wTFf9W0PpzBvIGQBACYmLm7yOMCqDtB5f6hXak94UFo0lPMklO22ykFfg71mNyu3/ZkUNltz1b+7vYOQBQDgkCG7vMmxmWdkVyGfiWvH3rD9yWeb22O/KVdfuqVy29HZOBwuWKVmbEHIAgBw6JBdLMqKaryLMV3GwRFcqRykVXWt2g0V9KfyimV7rsEEbTkILLbDCXftqIGDvQAAOLTFsjtxwbrOzds6PJcpPT8pQnctlV6N/XlsBwd9lZXcsp/sbZXiuszJClkAAA4rzuclUpsl11UdoXcxxXm709Zg7rUp1fJ13KzKDnbfGhwQFu/qr1fdoGwUsgAAHD5kF32JlhD9E5ots+KiCv0JvAZzr3GzPUGJ235lNo8TpHjbBnF373QSz1PIAgBMLWSvrtoQTf3ga5YP0nqsP89jPgCs7dz2Q4xhu03T5mfuYnNyhTjYzSAE228BALDXv3//9aGf+/mf/5ai3Zy0q4wOrGOIv1NoznEwq0P3sv66yl+XLs0ztfV9wkOO2NieVKFP29SeKqyP2I/+fUIWAIDdZrP+6nDhdDMa0JyZ60+57LvPM9+0CJsfttq6NMetCVkAgIn57pXST0Zr7tOLEqzd552ELAAA3x2u3aV6zw8LWQAAvlKO1Vm5XHzmFwlZAABGE69CFgDgDb5z1vTnr3+m8BLmcL06VnMKWQCAwzRVt9rYHVWf5c2r8g4Bef/WVWi3tZq6WF6L6/DOmVchCwDwdcGWY+0q7N+ZKpa4vSj3y2F7H9ptr9IZvh5CFgDgm+UVx8UHgm0Ye7ehXaUVsEIWAOBLLEq0fTb+lqFdnb0d8WtxXS7fcq4EIQsA8HY5Pmc7bs9jAt0MbJ6HXZe460YLuhna7eDrVjF/j+x1yM9lHo48AytkAQAOY7EnYu9Cu7KadsRtd7DXqtzvqgTgdhTm3z2Gldmq/K0n0ZBCFgDgdd02UkM5UPNK6uMbf0eO2nyQV161XYanq5lX5fZTnpn91jGCfVUNAMB+OdwWOyL2f++I2KHH8rPrrds/cvDYV/XiTWhXkuOp/WEAAOy3axXy944QfY9uNXc7mK9P7Lnnlegf4UT/FV/IAgC8bHukII8HPB7g9z6W3/XSY32nvEK8DKe5SixkAQBecbkVcmlHfH7G9okRYvj+1c/chz9OLKqFLADAO23vUrAKhz0jV7dt10uP+dXhniP2YgxvjpAFANhvO+gejvAYD6885lfJK7D5oK44ljfH9lsAAPttL/o9HuExHl95zK+QdyS4HtubI2QBAPbbXp1cH+Ex1q885rEd4pS7J/F/GQAAvD1sx260EStkAQBelr4gZKtXHvNYlmOOWCELAPCy7X/2P8aBWBevPOYx5JXY2djfHCELALDf9oFYxzi+6PKVxzxGxF5N4c0RsgAA++3a4/WQ4wUxPF8ZfTji85lPJWKFLADAy3JUbp9565DbVF2H52cOWx3puczCCLfYErIAAB93vyM+DzEre7EjLO+P9Bzy+MJyam+MkAUAeNmf8HwngeUnO6raEZapPNYxem85xTdGyAIAvCwH5u2Ohsqnc/3IyuxF+dntDrsNh996K5aIjVN8Y4QsAMDr8tzq/Y6O+hHaA6jeEoqx3PfHjga7D8eZjZ2H42wZdhKcohYA4G1uw+5dBvKc61UJ0XxZh81esFW5zML+HQ9W4fmK7yHMwoR2KBCyAACf8zvs3oc1ltveG473R4rYqvydkyZkAQDeJ4fnQwnFj86ednO3x9pq6zN/m5AFAJiwVYnZbqzgrdGYAzavwu7aCeFQrs6l8YQsAMDH5BC9K5fcVHkmNR9YVQ3CNt8nz8s+DuL3mPJjz8/lDRCyAACf9/AFkfoWZzFSIGQBAF7x89c/Y/pzZ+fWdvaRBQCYhvm5PWEhCwAwftfn2HVCFgBg3GIJ2bMjZAEAxu06nNEBXkIWAGAaujOKnSUhCwAwXme7GitkAQDG66xXY2tJyAIAjNMsnPFqbG0tZAEAxun6zJ+/kAUAGKF8Bq9z77hHIQsAMD5XXoLwIGQBAMYlz8XOzvw1WAcrsgAAo2M1NoRV/iBkAQDGZeYlCPdCFgBgXHK7XYjYZrRAyAIAjMi5r8am+nI3rHoAAITsGNyWmBWyAAAjkncrOOexgjxSsBreIGQBAMbh8oyfew7Y2+0bhSwAgJA9ZQ+7Ivbcyx4AQMietvt9EStkAQDGIc/HntO/pKcSsCtlDwAwbufUbHkV9i4MdifwogAAjNfUdyvIJzhYhcHJDtQ9AMA0TGmsIJVYzZfH0B7M9fiRX/R/AQYA1i4UF+HkevkAAAAASUVORK5CYII=");
|
||||
background-size: 100% 100%;
|
||||
background-color: #fff9f9;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt {
|
||||
width: 445rpx;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .pictrue {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .pictrue .alter {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .text {
|
||||
width: 325rpx;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .text .name {
|
||||
width: 100%;
|
||||
font-size: 30rpx;
|
||||
color: #282828;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .picTxt .text .phone {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .bnt {
|
||||
font-size: 24rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 27rpx;
|
||||
width: 140rpx;
|
||||
height: 54rpx;
|
||||
border: 2rpx solid #e93323;
|
||||
}
|
||||
|
||||
.personal-data .wrapList .item .currentBnt {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
font-size: 26rpx;
|
||||
background-color: rgba(233, 51, 35, 0.1);
|
||||
width: 140rpx;
|
||||
height: 48rpx;
|
||||
border-radius: 0 20rpx 0 20rpx;
|
||||
}
|
||||
|
||||
.personal-data .list {
|
||||
// margin-top: 15rpx;
|
||||
background-color: #fff;
|
||||
|
||||
}
|
||||
|
||||
.personal-data .list .item {
|
||||
padding: 30rpx 30rpx 30rpx 0;
|
||||
border-bottom: 1rpx solid #f2f2f2;
|
||||
margin-left: 30rpx;
|
||||
font-size: 32rpx;
|
||||
color: #282828;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.personal-data .list .item .phone {
|
||||
width: 160rpx;
|
||||
height: 56rpx;
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
line-height: 56rpx;
|
||||
border-radius: 32rpx
|
||||
}
|
||||
|
||||
.personal-data .list .item .pictrue {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.personal-data .list .item .pictrue image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.personal-data .list .item .input {
|
||||
width: 415rpx;
|
||||
text-align: right;
|
||||
color: #868686;
|
||||
}
|
||||
|
||||
.personal-data .list .item .inputs {
|
||||
// width: 415rpx;
|
||||
text-align: right;
|
||||
color: #868686;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.personal-data .list .item .inputs .iconfont {
|
||||
font-size: 35rpx;
|
||||
margin-left: 30rpx;
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.personal-data .modifyBnt {
|
||||
font-size: 32rpx;
|
||||
color: #fff;
|
||||
width: 690rpx;
|
||||
height: 90rpx;
|
||||
text-align: center;
|
||||
line-height: 90rpx;
|
||||
margin: 76rpx auto 0 auto;
|
||||
background: #3875EA;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
|
||||
.personal-data .logOut {
|
||||
font-size: 32rpx;
|
||||
text-align: center;
|
||||
width: 690rpx;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
margin: 30rpx auto 0 auto;
|
||||
border: 1rpx solid #3875EA;
|
||||
color: #3875EA;
|
||||
}
|
||||
|
||||
.avatar-box {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user