init
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user