修改客服记录
This commit is contained in:
parent
8ea101637e
commit
ecb2bd247f
@ -4,10 +4,19 @@ NODE_ENV = production
|
|||||||
# 标题
|
# 标题
|
||||||
VUE_APP_TITLE = 象纬云科
|
VUE_APP_TITLE = 象纬云科
|
||||||
|
|
||||||
# 接口地址
|
# 测试环境
|
||||||
VUE_APP_API_BASEURL = https://dev.api.linkwing.com/api/v1
|
VUE_APP_API_BASEURL = https://dev.api.linkwing.com/api/v1
|
||||||
VUE_APP_API_DEV = https://dev.api.linkwing.com/api/v1
|
VUE_APP_API_DEV = https://dev.api.linkwing.com/api/v1
|
||||||
|
|
||||||
# WS地址
|
|
||||||
VUE_APP_WS_URL = wss://dev.api.linkwing.com/wss
|
VUE_APP_WS_URL = wss://dev.api.linkwing.com/wss
|
||||||
VUE_APP_WSS_URL = wss://dev.api.linkwing.com/wss
|
VUE_APP_WSS_URL = wss://dev.api.linkwing.com/wss
|
||||||
|
|
||||||
|
# 线上环境
|
||||||
|
# 接口地址
|
||||||
|
# VUE_APP_API_BASEURL = https://prod.api.linkwing.com/api/v1
|
||||||
|
# VUE_APP_API_DEV = https://prod.api.linkwing.com/api/v1
|
||||||
|
|
||||||
|
# WS地址
|
||||||
|
# VUE_APP_WS_URL = wss://prod.api.linkwing.com/wss
|
||||||
|
# VUE_APP_WSS_URL = wss://prod.api.linkwing.com/wss
|
||||||
|
|
||||||
|
|||||||
@ -65,4 +65,5 @@ export default {
|
|||||||
return await http.post(this.url, data);
|
return await http.post(this.url, data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,11 @@
|
|||||||
</el-avatar>
|
</el-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div class="msgText">
|
<div class="msgText">
|
||||||
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
<div class="msgTitle">
|
||||||
|
<span class="leftTime" v-if="user_id != item.to_user_id">{{item.created_at}}</span>
|
||||||
|
{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}
|
||||||
|
<span class="time" v-if="user_id === item.to_user_id">{{item.created_at}}</span>
|
||||||
|
</div>
|
||||||
<div class="textCom">
|
<div class="textCom">
|
||||||
<div v-html="item.to_message"></div>
|
<div v-html="item.to_message"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -37,7 +41,7 @@
|
|||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<el-input class="customTextarea" v-model="params.to_message" resize="none" type="textarea" :row="2" placeholder="请简短描述您的问题"></el-input>
|
<el-input class="customTextarea" v-model="params.to_message" @keydown="handleKeydown" resize="none" type="textarea" :row="2" placeholder="Shift+Enter换行 请简短描述您的问题"></el-input>
|
||||||
<div class="saveBtn" :class="params.to_message!==''?'saveActive':''" @click="sendCustomer">发 送</div>
|
<div class="saveBtn" :class="params.to_message!==''?'saveActive':''" @click="sendCustomer">发 送</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -136,6 +140,15 @@ export default {
|
|||||||
typeActive(item){
|
typeActive(item){
|
||||||
this.params.type = item.value;
|
this.params.type = item.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleKeydown(event){
|
||||||
|
if(event.key === 'Enter' && !event.shiftKey){
|
||||||
|
event.preventDefault(); // 阻止输入框的默认行为
|
||||||
|
this.sendCustomer();
|
||||||
|
}else if(event.key === 'Enter' && event.shiftKey){
|
||||||
|
this.params.to_message += '';
|
||||||
|
}
|
||||||
|
},
|
||||||
async sendCustomer() {
|
async sendCustomer() {
|
||||||
if(this.params.to_message =="") return
|
if(this.params.to_message =="") return
|
||||||
const res = await this.$API.customer.send.post(this.params);
|
const res = await this.$API.customer.send.post(this.params);
|
||||||
@ -180,7 +193,7 @@ export default {
|
|||||||
.customerBox{
|
.customerBox{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 40px;
|
right: 40px;
|
||||||
bottom: 40px;
|
bottom: 80px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
.img{
|
.img{
|
||||||
width: 56px;
|
width: 56px;
|
||||||
@ -240,7 +253,7 @@ export default {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
.msgItem{
|
.msgItem{
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 12px;
|
||||||
.avatar{
|
.avatar{
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
@ -248,11 +261,23 @@ export default {
|
|||||||
.msgTitle{
|
.msgTitle{
|
||||||
padding: 0 0 8px 0;
|
padding: 0 0 8px 0;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
.time{
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
.leftTime{
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,12 +288,14 @@ export default {
|
|||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
.msgText{
|
.msgText{
|
||||||
|
text-align: right;
|
||||||
.msgTitle{
|
.msgTitle{
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
background: var(--el-color-primary);
|
background: var(--el-color-primary);
|
||||||
color: var(--el-color-white);
|
color: var(--el-color-white);
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -287,6 +287,7 @@
|
|||||||
this.$store.commit("set_repair_count", res.data.list_repair_info.repair_count);
|
this.$store.commit("set_repair_count", res.data.list_repair_info.repair_count);
|
||||||
}
|
}
|
||||||
let apiMenu = tool.objCopy(tool.data.get("MENU"));
|
let apiMenu = tool.objCopy(tool.data.get("MENU"));
|
||||||
|
if(apiMenu.length<1) return
|
||||||
apiMenu.forEach(item=>{
|
apiMenu.forEach(item=>{
|
||||||
if(item.name == 'order'){
|
if(item.name == 'order'){
|
||||||
item.meta.tag = 0;
|
item.meta.tag = 0;
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { ElNotification, ElMessageBox, ElMessage } from 'element-plus';
|
|||||||
import sysConfig from "@/config";
|
import sysConfig from "@/config";
|
||||||
import tool from '@/utils/tool';
|
import tool from '@/utils/tool';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
|
import {closeSock} from "@/utils/websocket"
|
||||||
|
|
||||||
axios.defaults.baseURL = ''
|
axios.defaults.baseURL = ''
|
||||||
|
|
||||||
@ -52,7 +53,8 @@ axios.interceptors.response.use(
|
|||||||
done();
|
done();
|
||||||
},
|
},
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// closeSock(true);
|
closeSock(true);
|
||||||
|
tool.data.clear();
|
||||||
tool.cookie.remove("TOKEN");
|
tool.cookie.remove("TOKEN");
|
||||||
router.replace({ path: "/login" });
|
router.replace({ path: "/login" });
|
||||||
})
|
})
|
||||||
|
|||||||
@ -65,11 +65,15 @@ export default {
|
|||||||
fileType:{
|
fileType:{
|
||||||
type:String,
|
type:String,
|
||||||
default:'txt'
|
default:'txt'
|
||||||
|
},
|
||||||
|
size:{
|
||||||
|
type:String,
|
||||||
|
default:'large'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
size:'large'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
320
src/views/service/components/attachmentUpload.vue
Normal file
320
src/views/service/components/attachmentUpload.vue
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
<template>
|
||||||
|
<slot name="header"></slot>
|
||||||
|
|
||||||
|
<el-dialog v-bind="$attrs" :title="title" v-model="visible" :width="560" destroy-on-close draggable @closed="visible=false">
|
||||||
|
<div class="importBody" v-loading="saveLoading" element-loading-text="处理中...">
|
||||||
|
<el-upload
|
||||||
|
class="upload"
|
||||||
|
:action="oss.host"
|
||||||
|
:data="upload_data"
|
||||||
|
:file-list="fileList"
|
||||||
|
:show-file-list="false"
|
||||||
|
:on-success="handleSuccess"
|
||||||
|
:on-error="handleError"
|
||||||
|
:on-remove="handleRemove"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
|
:http-request="uploadFile"
|
||||||
|
drag
|
||||||
|
multiple
|
||||||
|
:auto-upload="true"
|
||||||
|
:limit="5"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<el-icon class="el-icon--upload"><sc-icon-Upload /></el-icon>
|
||||||
|
<div class="el-upload__text">
|
||||||
|
<span class="laText">请将附件拖到此处,或点击上传</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template #tip>
|
||||||
|
<div class="el-upload__tip">
|
||||||
|
<span class="tip">最多上传5个文件,单个文件不要超过10M,请上传 图片/xlsx/docx/zip 格式文件</span>
|
||||||
|
<span class="btn">
|
||||||
|
<slot name="download"></slot>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="importBox" v-if="progressShow && (fileList.length>0 || listProgress.length>0)">
|
||||||
|
<div v-if="uploadShow">
|
||||||
|
<div class="item" v-for="(item,index) in fileList" :key="item">
|
||||||
|
<div class="name">{{item.name}}</div>
|
||||||
|
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="0" />
|
||||||
|
<div class="deleteFile" @click="deleteFileNum(index)"><el-icon class="icon"><el-icon-Close/></el-icon></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<div class="item" v-for="(item) in listProgress" :key="item">
|
||||||
|
<div class="name">{{item.client_file_name}}</div>
|
||||||
|
<el-progress class="exportPopover" :text-inside="true" :stroke-width="12" :percentage="item.rate" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="close">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="save" :disabled="saveLoading">确 定</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {eventBus} from "@/utils/eventBus"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "attachmentUpload",
|
||||||
|
emits: ['closed', "uploadFileSuccess"],
|
||||||
|
props:{
|
||||||
|
size:{type:String, default:'small'},
|
||||||
|
title:{type:String, default: ""},
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
visible: false,
|
||||||
|
saveLoading:false,
|
||||||
|
fileList:[], // 正在上传的文件
|
||||||
|
listProgress:[], // 已上传的文件
|
||||||
|
|
||||||
|
oss:{
|
||||||
|
host:''
|
||||||
|
},
|
||||||
|
upload_data:{},
|
||||||
|
params:{},
|
||||||
|
parentParams:{
|
||||||
|
to_user_id:"",
|
||||||
|
unique:""
|
||||||
|
},
|
||||||
|
|
||||||
|
progressShow:false,
|
||||||
|
uploadShow:false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(){
|
||||||
|
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
eventBus.$on('sockBack', this.getWsResult);
|
||||||
|
},
|
||||||
|
unmounted() {
|
||||||
|
eventBus.$off('sockBack', this.getWsResult);
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
getWsResult(res){
|
||||||
|
if(res.data && (res.data.type == 12)){
|
||||||
|
this.progressShow = true;
|
||||||
|
if(this.listProgress.length==0){
|
||||||
|
this.listProgress.push(res.data);
|
||||||
|
}
|
||||||
|
let ids = this.listProgress.map(em=>em.file_unique_id);
|
||||||
|
if(!ids.includes(res.data.file_unique_id)){
|
||||||
|
this.listProgress.push(res.data);
|
||||||
|
}
|
||||||
|
this.listProgress.forEach(em=>{
|
||||||
|
if(em.file_unique_id == res.data.file_unique_id){
|
||||||
|
em.rate = res.data.rate
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let list = this.listProgress.filter(em=> em.rate != 100);
|
||||||
|
if(list.length==0 && res.data.status == 1){
|
||||||
|
this.progressShow = false;
|
||||||
|
}
|
||||||
|
if(res.data.status == 1){
|
||||||
|
this.fileList.splice(this.fileList[0],1);
|
||||||
|
this.params = {};
|
||||||
|
this.$emit('uploadFileSuccess');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 导入文件
|
||||||
|
importFile(params){
|
||||||
|
this.visible = true;
|
||||||
|
this.parentParams = params;
|
||||||
|
},
|
||||||
|
// 上传前
|
||||||
|
beforeUpload(file){
|
||||||
|
this.progressShow = true;
|
||||||
|
this.uploadShow = true;
|
||||||
|
this.fileList.push(file);
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async uploadFile() {
|
||||||
|
try {
|
||||||
|
this.setParamsData();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 数据处理
|
||||||
|
setParamsData(){
|
||||||
|
const formData = new FormData();
|
||||||
|
for(let i in this.fileList){
|
||||||
|
formData.append('files[]', this.fileList[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in this.upload_data) {
|
||||||
|
formData.append(key, this.upload_data[key]);
|
||||||
|
}
|
||||||
|
formData.append('to_user_id', this.parentParams['to_user_id']);
|
||||||
|
this.params = formData;
|
||||||
|
},
|
||||||
|
deleteFileNum(num){
|
||||||
|
this.handleRemove(this.fileList[num], this.fileList);
|
||||||
|
this.setParamsData();
|
||||||
|
},
|
||||||
|
close(){
|
||||||
|
this.visible = false;
|
||||||
|
this.progressShow = false;
|
||||||
|
this.listProgress = [];
|
||||||
|
this.handleRemove('',this.fileList,true);
|
||||||
|
},
|
||||||
|
async save() {
|
||||||
|
this.saveLoading = true;
|
||||||
|
const res = await this.$API.customer.attachmentMessage.post(this.params);
|
||||||
|
this.saveLoading = false;
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.$message.success('提交成功,正在上传');
|
||||||
|
this.listProgress = [];
|
||||||
|
this.visible = false;
|
||||||
|
// this.uploadShow = false;
|
||||||
|
// this.$emit('uploadFileSuccess');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleExceed(){
|
||||||
|
this.$message.warning('文件超出最大限制');
|
||||||
|
},
|
||||||
|
handleRemove(file,fileList,isArr=false){
|
||||||
|
if(isArr){
|
||||||
|
fileList = [];
|
||||||
|
// this.listProgress = [];
|
||||||
|
}else{
|
||||||
|
const index = fileList.findIndex(f => f.uid === file.uid);
|
||||||
|
if (index !== -1) {
|
||||||
|
fileList.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上传成功
|
||||||
|
handleSuccess(response, file, fileList){
|
||||||
|
const index = fileList.findIndex(f => f.uid === file.uid);
|
||||||
|
if (index !== -1) {
|
||||||
|
fileList.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上传失败
|
||||||
|
handleError(){
|
||||||
|
this.$message.warning('上传失败请重新上传');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.importBody{
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
.upload .el-icon--upload{
|
||||||
|
width: 54px;height: 54px;
|
||||||
|
}
|
||||||
|
.upload ::v-deep .el-upload__text{
|
||||||
|
.trueIcon{
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.laText{
|
||||||
|
color: var(--el-color-dark);
|
||||||
|
}
|
||||||
|
.tipText{
|
||||||
|
color: var(--el-text-color-placeholder);
|
||||||
|
}
|
||||||
|
.deleteFile{
|
||||||
|
position: absolute;
|
||||||
|
right: -6px;
|
||||||
|
top: -10px;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--el-color-danger);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.icon{
|
||||||
|
width: 12px;height: 12px;
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.upload ::v-deep .el-upload__tip{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 15px;
|
||||||
|
color: var(--el-text-color-placeholder);
|
||||||
|
.btn{
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.importBox{
|
||||||
|
border: 1px solid var(--el-border-color);
|
||||||
|
padding: 10px 5px;
|
||||||
|
margin: 15px 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
.item{
|
||||||
|
margin-bottom: 10px;position: relative;
|
||||||
|
.deleteFile{
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 1px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #AAAAAA;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
.icon{
|
||||||
|
width: 12px;height: 12px;
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.item:last-child{margin-bottom: 0;}
|
||||||
|
.name{margin-bottom: 5px;font-size: 13px;}
|
||||||
|
.exportPopover ::v-deep .el-progress-bar__innerText{
|
||||||
|
height: 100%;
|
||||||
|
display: flex;align-items: center;justify-content: flex-end;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.errText{
|
||||||
|
margin: 15px 0 0 0;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--el-color-danger-light-9);
|
||||||
|
position: relative;
|
||||||
|
.name{
|
||||||
|
color: var(--el-color-danger);
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.deleteErr{
|
||||||
|
position: absolute;
|
||||||
|
right: 4px;
|
||||||
|
top: 4px;
|
||||||
|
z-index: 20;
|
||||||
|
cursor: pointer;
|
||||||
|
.icon{
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,10 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div></div>
|
<el-dialog :title="titleMap[mode]" v-model="visible" :width="600" draggable destroy-on-close @closed="$emit('closed')">
|
||||||
|
<el-input placeholder="搜索"></el-input>
|
||||||
|
<el-tabs>
|
||||||
|
<el-tab-pane label="全部">
|
||||||
|
<records-list></records-list>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="文档">
|
||||||
|
647658
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import recordsList from "@/views/service/components/recordsList";
|
||||||
export default {
|
export default {
|
||||||
name: "customerRecords"
|
name:"customerRecords",
|
||||||
|
components:{
|
||||||
|
recordsList
|
||||||
|
},
|
||||||
|
emits: ['success', 'closed'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
mode: "show",
|
||||||
|
titleMap: {
|
||||||
|
show: '聊天记录',
|
||||||
|
},
|
||||||
|
visible: false,
|
||||||
|
isSave: false,
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//显示
|
||||||
|
open(mode='show'){
|
||||||
|
this.mode = mode;
|
||||||
|
this.visible = true;
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
//表单注入数据
|
||||||
|
async setData(data) {
|
||||||
|
let params = {
|
||||||
|
page:1,
|
||||||
|
pageSize:100,
|
||||||
|
to_user_id:data
|
||||||
|
}
|
||||||
|
await this.$API.customer.recordList.post(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
34
src/views/service/components/recordsList.vue
Normal file
34
src/views/service/components/recordsList.vue
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<div class="recordView">
|
||||||
|
<!-- <div class="itemCol" v-for="(item,index) in list">-->
|
||||||
|
<!-- <div class=""></div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "recordsList",
|
||||||
|
props:{
|
||||||
|
// list:{
|
||||||
|
// type:Array,
|
||||||
|
// default:[]
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
</el-aside>
|
</el-aside>
|
||||||
<el-main class="userMain userMainPadding_0" style="border-top-right-radius: 0;border-bottom-right-radius: 0;padding: 0;">
|
<el-main class="userMain userMainPadding_0" style="border-top-right-radius: 0;border-bottom-right-radius: 0;padding: 0;">
|
||||||
<div class="mainBody">
|
<div class="mainBody">
|
||||||
<div class="mainTitle">{{contactsInfo.to_user && contactsInfo.to_user.name?contactsInfo.to_user.name:"匿名"}}</div>
|
<div class="mainTitle">{{contactsInfo.from_user && contactsInfo.from_user.name?contactsInfo.from_user.name:"匿名"}}</div>
|
||||||
<div class="mainView">
|
<div class="mainView">
|
||||||
<el-scrollbar ref="scrollbar">
|
<el-scrollbar ref="scrollbar">
|
||||||
<div class="msgList">
|
<div class="msgList">
|
||||||
@ -37,18 +37,22 @@
|
|||||||
</el-avatar>
|
</el-avatar>
|
||||||
</div>
|
</div>
|
||||||
<div class="msgText">
|
<div class="msgText">
|
||||||
<div class="msgTitle">{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}</div>
|
<div class="msgTitle">
|
||||||
|
<span class="leftTime" v-if="user_id != item.to_user_id">{{item.created_at}}</span>
|
||||||
|
{{item.from_user && item.from_user.name?item.from_user.name:'匿名'}}
|
||||||
|
<span class="time" v-if="user_id === item.to_user_id">{{item.created_at}}</span>
|
||||||
|
</div>
|
||||||
<div class="textCom" v-if="item.send_message_type === 1">
|
<div class="textCom" v-if="item.send_message_type === 1">
|
||||||
<div v-html="item.to_message"></div>
|
<div v-html="item.to_message"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="textCom" v-if="item.send_message_type === 2">
|
<div class="textCom textComNoneBack" v-if="item.send_message_type === 2">
|
||||||
<div v-for="(em,ind) in item.to_message_list" :key="ind">
|
<div v-for="(em,ind) in item.to_message_list" :key="ind">
|
||||||
<span v-if="em.extension === 'xlsx'">
|
<span v-if="em.extension === 'png' || em.extension === 'jpg' || em.extension === 'gif' || em.extension === 'jpeg'">
|
||||||
文件 ====
|
|
||||||
</span>
|
|
||||||
<span v-else>
|
|
||||||
<el-image style="max-width: 280px;max-height: 240px;" fit="contain" :src="em.file?em.file:em" preview-teleported :preview-src-list="[em.file?em.file:em]"></el-image>
|
<el-image style="max-width: 280px;max-height: 240px;" fit="contain" :src="em.file?em.file:em" preview-teleported :preview-src-list="[em.file?em.file:em]"></el-image>
|
||||||
</span>
|
</span>
|
||||||
|
<span class="fileView" v-else>
|
||||||
|
<fileType size="60px" :fileType="em.extension" />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -63,12 +67,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mainFooter">
|
<div class="mainFooter">
|
||||||
<div class="tagList">
|
<div class="tagList">
|
||||||
<div class="tagItem"><el-icon size="18"><sc-icon-Attachment/></el-icon></div>
|
<div class="tagItem" @click="uploadFile"><el-icon size="18"><sc-icon-Attachment/></el-icon></div>
|
||||||
<div class="tagItem"><el-icon size="18"><sc-icon-Record/></el-icon></div>
|
<div class="tagItem" @click="recordsShow"><el-icon size="18"><sc-icon-Record/></el-icon></div>
|
||||||
<div class="tagItem"><el-icon size="18"><sc-icon-Expression/></el-icon></div>
|
<div class="tagItem"><el-icon size="18"><sc-icon-Expression/></el-icon></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sendView">
|
<div class="sendView">
|
||||||
<el-input v-model="params.to_message" class="customTextarea" type="textarea" placeholder="请输入.." :rows="3" resize="none"></el-input>
|
<el-input @keydown="handleKeydown" v-model="params.to_message" class="customTextarea" type="textarea" placeholder="Shift+Enter换行 请输入.." :rows="3" resize="none"></el-input>
|
||||||
<div class="saveBtn" @click="sendCustomer" :class="params.to_message!=''?'saveActive':''">
|
<div class="saveBtn" @click="sendCustomer" :class="params.to_message!=''?'saveActive':''">
|
||||||
<el-icon size="22"><sc-icon-SendCustom /></el-icon>
|
<el-icon size="22"><sc-icon-SendCustom /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
@ -104,12 +108,23 @@
|
|||||||
</el-container>
|
</el-container>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
</el-container>
|
</el-container>
|
||||||
|
|
||||||
|
<customer-records-dialog v-if="dialog.show" ref="recordsMsgDialog" @closed="dialog.show=false"></customer-records-dialog>
|
||||||
|
<uploadFile ref="uploadFile" @uploadFileSuccess="uploadFileSuccess" title="上传附件"></uploadFile>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {eventBus} from "@/utils/eventBus";
|
import {eventBus} from "@/utils/eventBus";
|
||||||
|
import customerRecordsDialog from "@/views/service/components/customerRecords"
|
||||||
|
import uploadFile from "@/views/service/components/attachmentUpload";
|
||||||
|
import fileType from "@/views/docsManager/fileType"
|
||||||
export default {
|
export default {
|
||||||
name: "", // faq
|
name: "", // faq
|
||||||
|
components:{
|
||||||
|
customerRecordsDialog,
|
||||||
|
uploadFile,
|
||||||
|
fileType
|
||||||
|
},
|
||||||
data(){
|
data(){
|
||||||
return{
|
return{
|
||||||
contactsList:[],
|
contactsList:[],
|
||||||
@ -121,6 +136,10 @@ export default {
|
|||||||
params:{
|
params:{
|
||||||
to_user_id:"",
|
to_user_id:"",
|
||||||
to_message:"",
|
to_message:"",
|
||||||
|
},
|
||||||
|
|
||||||
|
dialog:{
|
||||||
|
show:false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -178,6 +197,14 @@ export default {
|
|||||||
}
|
}
|
||||||
await this.$API.customer.list.post(params);
|
await this.$API.customer.list.post(params);
|
||||||
},
|
},
|
||||||
|
handleKeydown(event){
|
||||||
|
if(event.key === 'Enter' && !event.shiftKey){
|
||||||
|
event.preventDefault(); // 阻止输入框的默认行为
|
||||||
|
this.sendCustomer();
|
||||||
|
}else if(event.key === 'Enter' && event.shiftKey){
|
||||||
|
this.params.to_message += '';
|
||||||
|
}
|
||||||
|
},
|
||||||
async sendCustomer() {
|
async sendCustomer() {
|
||||||
if(this.params.to_message =="") return
|
if(this.params.to_message =="") return
|
||||||
const res = await this.$API.customer.send.post(this.params);
|
const res = await this.$API.customer.send.post(this.params);
|
||||||
@ -197,6 +224,23 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 上传附件
|
||||||
|
uploadFile(){
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.$refs.uploadFile.importFile(this.params);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
uploadFileSuccess(){
|
||||||
|
this.getCustomerMsgList();
|
||||||
|
},
|
||||||
|
|
||||||
|
recordsShow(){
|
||||||
|
this.dialog.show = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.recordsMsgDialog.open('show').setData(this.to_user_id);
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
scrollDown() {
|
scrollDown() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const wrap = this.$refs.scrollbar;
|
const wrap = this.$refs.scrollbar;
|
||||||
@ -305,7 +349,8 @@ export default {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
.msgItem{
|
.msgItem{
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 12px;
|
||||||
|
padding-right: 40px;
|
||||||
.avatar{
|
.avatar{
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
@ -313,27 +358,54 @@ export default {
|
|||||||
.msgTitle{
|
.msgTitle{
|
||||||
padding:0 0 8px 0;
|
padding:0 0 8px 0;
|
||||||
color: #555;
|
color: #555;
|
||||||
|
.time{
|
||||||
|
margin-left: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
.leftTime{
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: left;
|
||||||
|
.fileView{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.textComNoneBack{
|
||||||
|
background: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.msgRightItem{
|
.msgRightItem{
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
padding:0 0 0 40px;
|
||||||
.avatar{
|
.avatar{
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 0;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
.msgText{
|
.msgText{
|
||||||
|
text-align: right;
|
||||||
.msgTitle{
|
.msgTitle{
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
.textCom{
|
.textCom{
|
||||||
background: var(--el-color-primary);
|
background: var(--el-color-primary);
|
||||||
color: var(--el-color-white);
|
color: var(--el-color-white);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.textComNoneBack{
|
||||||
|
background: none;
|
||||||
|
.el-image{
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,6 +427,7 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.customTextarea{
|
.customTextarea{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user