|
@@ -1,1251 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <div class="global-im">
|
|
|
|
|
- <!-- 悬浮按钮与角标 -->
|
|
|
|
|
- <div class="im-trigger" :class="{ active: visible }" @click="toggleChat">
|
|
|
|
|
- <el-icon :size="18"><el-icon-chat-round /></el-icon>
|
|
|
|
|
- <div class="unreadCount">
|
|
|
|
|
- <el-badge :value="unreadCount" :hidden="unreadCount === 0" :max="99">
|
|
|
|
|
- <i class="el-icon-chat-dot-round" style="font-size: 24px"></i>
|
|
|
|
|
- </el-badge>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-drawer v-model="visible" title="在线客服" size="100%" destroy-on-close :close-on-click-modal="false" :with-header="false">
|
|
|
|
|
- <el-container class="flex-column">
|
|
|
|
|
- <div class="drawer-detail-main">
|
|
|
|
|
- <div class="drawer-detail-header">
|
|
|
|
|
- <div class="drawer-detail-header-body">
|
|
|
|
|
- <div class="drawer-detail-header-left">在线客服</div>
|
|
|
|
|
- <div class="drawer-detail-header-left">
|
|
|
|
|
- <el-button type="default" icon="el-icon-close" round @click="hideWindow"></el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-main class="nopadding">
|
|
|
|
|
- <el-container>
|
|
|
|
|
- <el-aside width="300px" v-loading="loadMsg">
|
|
|
|
|
- <el-container class="flex-column">
|
|
|
|
|
- <!-- <div class="aside-tabs bg">
|
|
|
|
|
- <div :class="orderData.tab=='user'?'aside-tab-items active':'aside-tab-items'" @click="handleClick('user')">当前咨询</div>
|
|
|
|
|
- <div :class="orderData.tab=='order'?'aside-tab-items active':'aside-tab-items'" @click="handleClick('order')">历史咨询</div>
|
|
|
|
|
- </div> -->
|
|
|
|
|
- <el-main class="nopadding">
|
|
|
|
|
- <div class="chat-contact">
|
|
|
|
|
- <div :class="checkChat==index?'contact-item active':'contact-item'" v-for="(item,index) in chatContact" :key="index" @click="checkChatItem(index)">
|
|
|
|
|
- <div class="img">
|
|
|
|
|
- <el-image :src="item.user.avatar" fit="contain" style="width: 40px; height: 40px"></el-image>
|
|
|
|
|
- <span class="last-num" v-if="item.last.num > 0">{{item.last.num}}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="kefu-store">
|
|
|
|
|
- <div class="name">{{item.user.nickname}}</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='text'">{{item.last.content}}</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='order'">[订单消息]</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='image'">[图片消息]</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='video'">[视频消息]</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='pay'">[支付消息]</div>
|
|
|
|
|
- <div class="desc" v-if="item.last.type=='address'">[收集地址]</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="time">
|
|
|
|
|
- {{item.last.create_at}}
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </el-aside>
|
|
|
|
|
- <el-container v-if="chatItem">
|
|
|
|
|
- <el-header><div class="msg-title">与{{ chatItem.user.nickname }}的对话</div></el-header>
|
|
|
|
|
- <el-main class="nopadding" ref="main">
|
|
|
|
|
- <div class="chat-container" v-if="chatItem">
|
|
|
|
|
- <div class="loading-text" v-if="msgLoad">努力加载中...</div>
|
|
|
|
|
- <div class="message-list" ref="messageListRef" @scroll="handleScroll">
|
|
|
|
|
- <template v-for="(item, index) in history.messages">
|
|
|
|
|
- <div class="z_index2" style="transform: rotate(-180deg)" :key="item.messageId" v-if="!item.isHide">
|
|
|
|
|
- <div class="icon_ text_26 color__ time">
|
|
|
|
|
- {{ renderMessageDate(item, index) }}
|
|
|
|
|
- </div>
|
|
|
|
|
- <div :key="item.messageIds" v-if="!item.recalled">
|
|
|
|
|
- <item :isMy="isSelf(item.senderId)" :myid="myid" :item="item" @onClick="onItem"
|
|
|
|
|
- @onLongpress="onLongpress" @mention="mention"></item>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="icon_ text_26 recalled" v-else>
|
|
|
|
|
- <div class="">
|
|
|
|
|
- <span v-if="isSelf(item.senderId)">你</span>
|
|
|
|
|
- <span v-else>{{ item.senderData.name }}</span>
|
|
|
|
|
- 撤回了一条消息
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="recalled-edit" v-if="item.type === 'text' && isSelf(item.senderId)"
|
|
|
|
|
- @click="recalledEdit(item)">重新编辑</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="input-area">
|
|
|
|
|
- <div class="quick-group">
|
|
|
|
|
- <div class="emoji-item">
|
|
|
|
|
- <el-popover placement="top" :width="400" trigger="click">
|
|
|
|
|
- <template #reference>
|
|
|
|
|
- <div class="item-btn">
|
|
|
|
|
- <el-image style="width:25px;height:25px;" src="https://jymini.oss-cn-guangzhou.aliyuncs.com/pc/face.svg"></el-image>
|
|
|
|
|
- <div class="name">表情</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- <div class="swiper-item-box">
|
|
|
|
|
- <div class="flex_r swiper-item-box-l" v-for="(im, ix) in emojiList" :key="ix">
|
|
|
|
|
- <div
|
|
|
|
|
- class="icon_ emoji-item"
|
|
|
|
|
- v-for="(item, index) in im"
|
|
|
|
|
- :key="index"
|
|
|
|
|
- :style="{ opacity: ix === opacityGroup && (index == 5 || index == 6 || index == 7) ? opacity : 1 }"
|
|
|
|
|
- >
|
|
|
|
|
- <el-image class="img" :src="emojiUrl + item.image" @click="chooseEmoji(item.text)"></el-image>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-popover>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="emoji-item">
|
|
|
|
|
- <el-popover placement="top" :width="174">
|
|
|
|
|
- <template #reference>
|
|
|
|
|
- <div class="item-btn">
|
|
|
|
|
- <el-image style="width:25px;height:25px;" src="https://jymini.oss-cn-guangzhou.aliyuncs.com/pc/more.svg"></el-image>
|
|
|
|
|
- <div class="name">图片</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- <sc-upload v-model="uploadImg" :on-success="uploadSuccess"></sc-upload>
|
|
|
|
|
- </el-popover>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="emoji-item" @click="showQuick">
|
|
|
|
|
- <el-popover placement="top" :width="400" trigger="click" @show="getQuick">
|
|
|
|
|
- <template #reference>
|
|
|
|
|
- <div class="item-btn">
|
|
|
|
|
- <el-image style="width:25px;height:25px;" src="https://jymini.oss-cn-guangzhou.aliyuncs.com/pc/quick.svg"></el-image>
|
|
|
|
|
- <div class="name">快捷回复</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- <div class="quick-table">
|
|
|
|
|
- <div class="quick-search">
|
|
|
|
|
- <div class="search-input">
|
|
|
|
|
- <el-input placeholder="搜索一下..." style="width: 100%;" />
|
|
|
|
|
- <el-button>搜索</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="search-btn-txt"><el-button type="primary" @click="addQuick">添加</el-button></div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="quick-table-body">
|
|
|
|
|
- <el-table :data="quickData.list" style="width: 100%" height="300" border>
|
|
|
|
|
- <el-table-column prop="content" label="内容"></el-table-column>
|
|
|
|
|
- <el-table-column prop="content" label="操作" width="80">
|
|
|
|
|
- <template #default="scope">
|
|
|
|
|
- <el-button size="small" @click="sendQuick(scope.row.content)">发送</el-button>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-table-column>
|
|
|
|
|
- </el-table>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="quick-page">
|
|
|
|
|
- <el-pagination
|
|
|
|
|
- small
|
|
|
|
|
- background
|
|
|
|
|
- layout="prev, pager, next"
|
|
|
|
|
- :total="quickData.total"
|
|
|
|
|
- @size-change="quickPageChange" @current-change="quickPageChange"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-popover>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-input
|
|
|
|
|
- type="textarea"
|
|
|
|
|
- :rows="3"
|
|
|
|
|
- v-model="inputMessage"
|
|
|
|
|
- placeholder="请输入消息..."
|
|
|
|
|
- @keyup.enter.native="handleKeyCode"
|
|
|
|
|
- @keydown.native="handleKeyCode"
|
|
|
|
|
- ></el-input>
|
|
|
|
|
- <div class="send-btn-group">
|
|
|
|
|
- <div class="send-btn-right">
|
|
|
|
|
- <el-button type="primary" @click="sendMessage">发送</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- <el-container v-else>
|
|
|
|
|
- <div class="empty-data">
|
|
|
|
|
- 请选择左侧的聊天列表
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- <el-aside width="400px" v-if="chatItem">
|
|
|
|
|
- <el-container class="flex-column">
|
|
|
|
|
- <div class="aside-tabs">
|
|
|
|
|
- <div :class="orderData.tab=='user'?'aside-tab-items active':'aside-tab-items'" @click="handleClick('user')">用户信息</div>
|
|
|
|
|
- <div :class="orderData.tab=='order'?'aside-tab-items active':'aside-tab-items'" @click="handleClick('order')">团购订单</div>
|
|
|
|
|
- <div :class="orderData.tab=='price'?'aside-tab-items active':'aside-tab-items'" @click="handleClick('price')">差价订单</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <el-main class="nopadding">
|
|
|
|
|
- <template v-if="orderData.tab == 'user'">
|
|
|
|
|
- <div class="order-info-user">
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <div class="name">昵称</div>
|
|
|
|
|
- <div class="right">{{ chatItem.user.nickname }} </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <div class="name">OpenId</div>
|
|
|
|
|
- <div class="right">{{ chatItem.user.openid }} </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <div class="name">手机号码</div>
|
|
|
|
|
- <div class="right">{{ chatItem.user.mobile }} </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-item">
|
|
|
|
|
- <div class="name">注册时间</div>
|
|
|
|
|
- <div class="right">{{ chatItem.user.create_at }} </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-info-user" v-if="msgOrder">
|
|
|
|
|
- <div class="title">咨询订单</div>
|
|
|
|
|
- <div class="m-order-s" style="margin-top: 15px;">
|
|
|
|
|
- <div class="m-order-item">
|
|
|
|
|
- <div class="order-img"><el-image style="width: 80px;height: 80px;" :src="msgOrder.img" fit="fit"></el-image></div>
|
|
|
|
|
- <div class="order-info">
|
|
|
|
|
- <div class="title" style="padding: 0;">{{msgOrder.product.product_name}}</div>
|
|
|
|
|
- <div class="desc" v-if="msgOrder.sku_name">规格:{{msgOrder.sku_name}}</div>
|
|
|
|
|
- <div class="desc">{{msgOrder.order_sn}}</div>
|
|
|
|
|
- <div class="price">
|
|
|
|
|
- {{$TOOL.money(msgOrder.price)}}
|
|
|
|
|
- <text v-if="msgOrder.custom_price > 0">差价:{{$TOOL.money(msgOrder.custom_price)}}</text>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-status-btn">
|
|
|
|
|
- <div class="status info" v-if="msgOrder.status=='0'">未支付</div>
|
|
|
|
|
- <div class="status primary" v-if="msgOrder.status=='1'">待使用</div>
|
|
|
|
|
- <div class="status success" v-if="msgOrder.status=='2'">已完成</div>
|
|
|
|
|
- <div class="status danger" v-if="msgOrder.status=='3'">已退款</div>
|
|
|
|
|
- <div class="status warn" v-if="msgOrder.status=='4'">退款中</div>
|
|
|
|
|
- <div class="status warn" v-if="msgOrder.status=='5'">已关闭</div>
|
|
|
|
|
- <div class="status success" v-if="msgOrder.product.product_type==11 && msgOrder.custom_price > 0 && msgOrder.custom_status ==1">差价已付</div>
|
|
|
|
|
- <div class="status danger" v-if="msgOrder.product.product_type==11 && msgOrder.custom_price > 0 && msgOrder.custom_status ==0">差价未付</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-btn-group">
|
|
|
|
|
- <div class="status info cus" @click="viewOrder(msgOrder)">查看详情</div>
|
|
|
|
|
- <div class="status primary cus" @click="sendAddress(msgOrder)">收集地址</div>
|
|
|
|
|
- <!-- <div class="status warn cus" v-if="msgOrder.product.product_type==11 && msgOrder.custom_price > 0 && msgOrder.custom_status ==0" @click="submitPrice(msgOrder)">补差价</div> -->
|
|
|
|
|
- <!-- <div class="status danger cus" v-if="msgOrder.product.product_type==11 && msgOrder.custom_price > 0 && msgOrder.custom_status ==0" @click="submitPrice(msgOrder)">改差价</div> -->
|
|
|
|
|
- <div class="status danger cus" @click="sendOrder(msgOrder)">发送订单</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-if="orderData.tab == 'price'">
|
|
|
|
|
- <el-container>
|
|
|
|
|
- <el-header>
|
|
|
|
|
- <div class="order-search-input">
|
|
|
|
|
- <el-input v-model="priceData.order" placeholder="搜索订单编号..." style="width: 100%;" />
|
|
|
|
|
- <el-button @click="searchPrice">搜索</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-header>
|
|
|
|
|
- <el-main>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- <el-footer style="text-align: right;">
|
|
|
|
|
- <div class="order-page">
|
|
|
|
|
- <el-pagination small background :default-page-size="priceData.size" layout="prev, pager, next" @size-change="orderPageChange" @current-change="orderPageChange" :total="priceData.total" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-footer>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-if="orderData.tab == 'order'">
|
|
|
|
|
- <el-container v-loading="orderData.loading">
|
|
|
|
|
- <el-header>
|
|
|
|
|
- <div class="order-search-input">
|
|
|
|
|
- <el-input v-model="orderData.order" placeholder="搜索订单编号..." style="width: 100%;" />
|
|
|
|
|
- <el-button @click="searchOrder">搜索</el-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-header>
|
|
|
|
|
- <el-main>
|
|
|
|
|
- <div class="order-list-chat" v-if="orderData.list.length > 0">
|
|
|
|
|
- <div class="m-order-s" v-for="(item,index) in orderData.list" :key="index">
|
|
|
|
|
- <div class="m-order-item">
|
|
|
|
|
- <div class="order-img"><el-image style="width: 80px;height: 80px;" :src="item.img" fit="fit"></el-image></div>
|
|
|
|
|
- <div class="order-info">
|
|
|
|
|
- <div class="title">{{item.product.product_name}}</div>
|
|
|
|
|
- <div class="desc" v-if="item.sku_name">规格:{{item.sku_name}}</div>
|
|
|
|
|
- <div class="desc">{{item.order_sn}}</div>
|
|
|
|
|
- <div class="price">
|
|
|
|
|
- {{$TOOL.money(item.price)}}
|
|
|
|
|
- <text v-if="item.custom_price > 0">差价:{{$TOOL.money(item.custom_price)}}</text>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-status-btn">
|
|
|
|
|
- <div class="status info" v-if="item.status=='0'">未支付</div>
|
|
|
|
|
- <div class="status primary" v-if="item.status=='1'">待使用</div>
|
|
|
|
|
- <div class="status success" v-if="item.status=='2'">已完成</div>
|
|
|
|
|
- <div class="status danger" v-if="item.status=='3'">已退款</div>
|
|
|
|
|
- <div class="status warn" v-if="item.status=='4'">退款中</div>
|
|
|
|
|
- <div class="status warn" v-if="item.status=='5'">已关闭</div>
|
|
|
|
|
- <div class="status success" v-if="item.product.product_type==11 && item.custom_price > 0 && item.custom_status ==1">差价已付</div>
|
|
|
|
|
- <div class="status danger" v-if="item.product.product_type==11 && item.custom_price > 0 && item.custom_status ==0">差价未付</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-btn-group">
|
|
|
|
|
- <div class="status info cus" @click="viewOrder(item)">查看详情</div>
|
|
|
|
|
- <div class="status primary cus" @click="sendAddress(item)">收集地址</div>
|
|
|
|
|
- <!-- <div class="status warn cus" v-if="item.product.product_type==11 && item.custom_price > 0 && item.custom_status ==0" @click="submitPrice(item)">补差价</div>
|
|
|
|
|
- <div class="status danger cus" v-if="item.product.product_type==11 && item.custom_price > 0 && item.custom_status ==0" @click="submitPrice(item)">改差价</div> -->
|
|
|
|
|
- <div class="status danger cus" @click="sendOrder(item)">发送订单</div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="order-list-chat" v-else>
|
|
|
|
|
- <el-empty description="没有订单" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- <el-footer style="text-align: right;">
|
|
|
|
|
- <div class="order-page">
|
|
|
|
|
- <el-pagination small background :default-page-size="orderData.size" layout="prev, pager, next" @size-change="orderPageChange" @current-change="orderPageChange" :total="orderData.total" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </el-footer>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </el-aside>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </el-main>
|
|
|
|
|
- </el-container>
|
|
|
|
|
- </el-drawer>
|
|
|
|
|
- <orderDetail ref="orderDetail" @success="orderSuccess"></orderDetail>
|
|
|
|
|
- <quickTxt ref="quickTxt" @success="orderSuccess"></quickTxt>
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script>
|
|
|
|
|
-import {
|
|
|
|
|
- mapState
|
|
|
|
|
-} from 'vuex';
|
|
|
|
|
-import { Push } from "@/utils/push";
|
|
|
|
|
-import { emojiMap } from "@/utils/emoji";
|
|
|
|
|
-import item from '@/components/chat/index';
|
|
|
|
|
-var pushObj = null;
|
|
|
|
|
-let height2 = null;
|
|
|
|
|
-const emojiUrl = 'https://imgcache.qq.com/open/qcloud/tim/assets/emoji/';
|
|
|
|
|
-import {
|
|
|
|
|
- formatDate,
|
|
|
|
|
- to as tofn
|
|
|
|
|
-} from '@/util/index.js';
|
|
|
|
|
-import orderDetail from '@/components/imFloat/order';
|
|
|
|
|
-import quickTxt from '@/components/imFloat/quickTxt';
|
|
|
|
|
-let imageList = [];
|
|
|
|
|
-export default {
|
|
|
|
|
- name: 'GlobalIM',
|
|
|
|
|
- components:{
|
|
|
|
|
- item,
|
|
|
|
|
- orderDetail,
|
|
|
|
|
- quickTxt
|
|
|
|
|
- },
|
|
|
|
|
- props: {
|
|
|
|
|
- user: { type: Object, default: () => {} }
|
|
|
|
|
- },
|
|
|
|
|
- data() {
|
|
|
|
|
- return {
|
|
|
|
|
- activeName:"user",
|
|
|
|
|
- rules:{
|
|
|
|
|
- name: [
|
|
|
|
|
- {required: true, message: '请输入'}
|
|
|
|
|
- ],
|
|
|
|
|
- price: [
|
|
|
|
|
- {required: true, message: '请输入'}
|
|
|
|
|
- ],
|
|
|
|
|
- },
|
|
|
|
|
- priceForm:{
|
|
|
|
|
- name:"补差价"
|
|
|
|
|
- },
|
|
|
|
|
- uploadImg:"",
|
|
|
|
|
- loadMsg:false,
|
|
|
|
|
- history: {
|
|
|
|
|
- messages: [],
|
|
|
|
|
- allLoaded: false
|
|
|
|
|
- },
|
|
|
|
|
- msgLoad:false,
|
|
|
|
|
- emojiUrl,
|
|
|
|
|
- loading:false,
|
|
|
|
|
- visible: false, // 聊天窗口可见性
|
|
|
|
|
- unreadCount: 0, // 未读消息数量
|
|
|
|
|
- inputMessage: '', // 输入的消息
|
|
|
|
|
- timer: null, // 定时器
|
|
|
|
|
- messages: [],
|
|
|
|
|
- wsAuth:"https://tran.jsshuita.cn/plugin/webman/push/auth",
|
|
|
|
|
- wsUrl: 'wss://tran.jsshuita.cn/ws',
|
|
|
|
|
- // wsAuth:"http://127.0.0.1:9981/plugin/webman/push/auth",
|
|
|
|
|
- // wsUrl: 'ws://127.0.0.1:3131',
|
|
|
|
|
- page:1,
|
|
|
|
|
- size:10,
|
|
|
|
|
- msgPage:1,
|
|
|
|
|
- msgSize:20,
|
|
|
|
|
- orderSize:10,
|
|
|
|
|
- chatContact:[],
|
|
|
|
|
- checkChat:null,
|
|
|
|
|
- chatItem:null,
|
|
|
|
|
- emojiList:[],
|
|
|
|
|
- sendId:null,
|
|
|
|
|
- myid: this.user.userId,
|
|
|
|
|
- userId:null,
|
|
|
|
|
- isSaveing:false,
|
|
|
|
|
- quickData:{
|
|
|
|
|
- page:1,
|
|
|
|
|
- size:10,
|
|
|
|
|
- list:[],
|
|
|
|
|
- popState:false,
|
|
|
|
|
- total:0
|
|
|
|
|
- },
|
|
|
|
|
- msgOrder:null, // 咨询订单
|
|
|
|
|
- orderData:{
|
|
|
|
|
- page:1,
|
|
|
|
|
- size:10,
|
|
|
|
|
- list:[],
|
|
|
|
|
- loading:false,
|
|
|
|
|
- total:0,
|
|
|
|
|
- tab:"user",
|
|
|
|
|
- order:""
|
|
|
|
|
- },
|
|
|
|
|
- priceData:{
|
|
|
|
|
- page:1,
|
|
|
|
|
- size:10,
|
|
|
|
|
- list:[],
|
|
|
|
|
- loading:false,
|
|
|
|
|
- total:0,
|
|
|
|
|
- order:""
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- watch: {
|
|
|
|
|
- chatItem(val){
|
|
|
|
|
- if (val) {
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- this.$refs.messageListRef?.addEventListener('scroll', this.handleScroll)
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- computed: mapState({
|
|
|
|
|
- //显示时间
|
|
|
|
|
- renderMessageDate() {
|
|
|
|
|
- return (message, index) => {
|
|
|
|
|
- if (message.timestamp - this.history.messages[index + 1]?.timestamp > 3 * 60 * 1000) {
|
|
|
|
|
- return formatDate(message.timestamp, 'timestamp');
|
|
|
|
|
- }
|
|
|
|
|
- return '';
|
|
|
|
|
- };
|
|
|
|
|
- },
|
|
|
|
|
- // 是否本人isMy
|
|
|
|
|
- isSelf() {
|
|
|
|
|
- return (senderId) => {
|
|
|
|
|
- const {
|
|
|
|
|
- member_id = this.myid
|
|
|
|
|
- } = {"member_id":this.myid};
|
|
|
|
|
- return senderId === `${member_id}`;
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
- }),
|
|
|
|
|
- mounted() {
|
|
|
|
|
- // console.log("pushObj")
|
|
|
|
|
- this.initEmoji()
|
|
|
|
|
- this.initPush();
|
|
|
|
|
- // this.simulateNewMessage()
|
|
|
|
|
- },
|
|
|
|
|
- beforeDestroy() {
|
|
|
|
|
- // if (this.timer) {
|
|
|
|
|
- // clearInterval(this.timer)
|
|
|
|
|
- // }
|
|
|
|
|
- this.$refs.messageListRef.removeEventListener('scroll', this.handleScroll)
|
|
|
|
|
- },
|
|
|
|
|
- methods: {
|
|
|
|
|
- handleClick(event){
|
|
|
|
|
- this.orderData.tab = event;
|
|
|
|
|
- switch (event) {
|
|
|
|
|
- case "user":
|
|
|
|
|
- break;
|
|
|
|
|
- case "order":
|
|
|
|
|
- this.orderData.page = 1;
|
|
|
|
|
- this.orderData.list = [];
|
|
|
|
|
- this.getOrderList();
|
|
|
|
|
- break;
|
|
|
|
|
- case "price":
|
|
|
|
|
- this.priceData.page = 1;
|
|
|
|
|
- this.priceData.list = [];
|
|
|
|
|
- this.getOrderPrice();
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- searchOrder(){
|
|
|
|
|
- this.orderData.page = 1;
|
|
|
|
|
- this.orderData.list = [];
|
|
|
|
|
- this.getOrderList();
|
|
|
|
|
- },
|
|
|
|
|
- searchPrice(){
|
|
|
|
|
- this.priceData.page = 1;
|
|
|
|
|
- this.priceData.list = [];
|
|
|
|
|
- this.getOrderPrice();
|
|
|
|
|
- },
|
|
|
|
|
- getOrderPrice(){
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
- viewOrder(data){
|
|
|
|
|
- data.order = data.out_order_no;
|
|
|
|
|
- this.$refs.orderDetail.open("add").setData(data)
|
|
|
|
|
- },
|
|
|
|
|
- quickPageChange(e){
|
|
|
|
|
- this.quickData.page = e;
|
|
|
|
|
- this.getQuick()
|
|
|
|
|
- },
|
|
|
|
|
- async getQuick(){
|
|
|
|
|
- var resp = await this.$API.merQuick.list.get({"page":this.quickData.page,"pageSize":this.quickData.size});
|
|
|
|
|
- if (resp.code == 0) {
|
|
|
|
|
- return this.$message.error(resp.msg)
|
|
|
|
|
- }
|
|
|
|
|
- this.quickData.total = resp.data.total;
|
|
|
|
|
- this.quickData.list = resp.data.rows;
|
|
|
|
|
- },
|
|
|
|
|
- addQuick(){
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- this.$refs.quickTxt.open("add")
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
- sendQuick(text){
|
|
|
|
|
- this.inputMessage = text;
|
|
|
|
|
- this.sendMessage()
|
|
|
|
|
- },
|
|
|
|
|
- orderSuccess(type,data){
|
|
|
|
|
- switch(type) {
|
|
|
|
|
- case "address":
|
|
|
|
|
- this.sendAddress(data)
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- async submitPrice(data){
|
|
|
|
|
- var { priceForm,$message } = this;
|
|
|
|
|
- if (data.custom_status == 1) return $message.error("该订单差价已完成支付")
|
|
|
|
|
- // var validate = await this.$refs.priceForm.validate().catch(()=>{});
|
|
|
|
|
- // if(!validate){ return false }
|
|
|
|
|
- this.isSaveing = true;
|
|
|
|
|
- priceForm.name = "订单差额补款";
|
|
|
|
|
- priceForm.price = parseInt(data.custom_price) / 100;
|
|
|
|
|
- priceForm.type = "pay";
|
|
|
|
|
- priceForm.groupId = this.chatItem.poi_id
|
|
|
|
|
- priceForm.openid = this.chatItem.openid
|
|
|
|
|
- var resp = await this.$API.chat.price.post(priceForm);
|
|
|
|
|
- this.isSaveing = false;
|
|
|
|
|
- if (resp.code == 0) {
|
|
|
|
|
- return $message.error(resp.msg)
|
|
|
|
|
- }
|
|
|
|
|
- this.sendMessageData({
|
|
|
|
|
- payload: {
|
|
|
|
|
- pay: resp.data,
|
|
|
|
|
- },
|
|
|
|
|
- type: 'pay'
|
|
|
|
|
- });
|
|
|
|
|
- this.uploadImg = "";
|
|
|
|
|
- },
|
|
|
|
|
- orderPageChange(e){
|
|
|
|
|
- this.orderData.page = e;
|
|
|
|
|
- this.getOrderList()
|
|
|
|
|
- },
|
|
|
|
|
- hideWindow(){
|
|
|
|
|
- this.chatItem = null;
|
|
|
|
|
- this.msgPage = 1;
|
|
|
|
|
- this.unreadCount = 0;
|
|
|
|
|
- this.checkChat = null;
|
|
|
|
|
- this.visible = false;
|
|
|
|
|
- },
|
|
|
|
|
- handleScroll(e){
|
|
|
|
|
- const { scrollTop, clientHeight, scrollHeight } = e.target
|
|
|
|
|
- const isBottom = scrollTop + clientHeight >= scrollHeight - 5 // 5px 缓冲区
|
|
|
|
|
- const isTop = scrollTop <= 5
|
|
|
|
|
- // console.log("滚动",this.history.allLoaded)
|
|
|
|
|
- if (isBottom && !this.history.allLoaded) {
|
|
|
|
|
- console.log('到达底部')
|
|
|
|
|
- // 加载更多等操作
|
|
|
|
|
- this.getMsgMore()
|
|
|
|
|
- }
|
|
|
|
|
- if (isTop && this.history.allLoaded) {
|
|
|
|
|
- // console.log('到达顶部')
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- playAudio(){
|
|
|
|
|
- const audio = new Audio('/img/msn.mp3');
|
|
|
|
|
- audio.play().catch(error => {
|
|
|
|
|
- console.error("播放音频时出错:", error);
|
|
|
|
|
- });
|
|
|
|
|
- },
|
|
|
|
|
- onLongpress(){},
|
|
|
|
|
- onItem(data){
|
|
|
|
|
- switch(data.type)
|
|
|
|
|
- {
|
|
|
|
|
- case "order":
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- this.$refs.orderDetail.open("add").setData(data.payload.order)
|
|
|
|
|
- })
|
|
|
|
|
- break;
|
|
|
|
|
- case "address":
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- this.$refs.orderDetail.open("add").setData(data.payload.address)
|
|
|
|
|
- })
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- chooseEmoji(data){
|
|
|
|
|
- this.inputMessage += data;
|
|
|
|
|
- },
|
|
|
|
|
- initEmoji() {
|
|
|
|
|
- let newList = [];
|
|
|
|
|
- let i = 1;
|
|
|
|
|
- for (let key in emojiMap) {
|
|
|
|
|
- let obj = {};
|
|
|
|
|
- obj['index'] = i;
|
|
|
|
|
- obj['text'] = key;
|
|
|
|
|
- obj['image'] = emojiMap[key];
|
|
|
|
|
- i++;
|
|
|
|
|
- newList.push(obj);
|
|
|
|
|
- }
|
|
|
|
|
- var list = [];
|
|
|
|
|
- let A = newList.filter((item, index) => {
|
|
|
|
|
- return (index + 1) % 8 === 0;
|
|
|
|
|
- });
|
|
|
|
|
- A.unshift({ index: 0 });
|
|
|
|
|
- A.push({ index: newList.length });
|
|
|
|
|
- this.emojiList = A.map((item, index) => {
|
|
|
|
|
- return newList.slice(A[index].index, A[index + 1]?.index || newList.length);
|
|
|
|
|
- });
|
|
|
|
|
- // this.scroll({ detail: { scrollTop: 10 } });
|
|
|
|
|
- },
|
|
|
|
|
- /**
|
|
|
|
|
- * 发送订单消息
|
|
|
|
|
- * @param data
|
|
|
|
|
- */
|
|
|
|
|
- async sendOrder(data){
|
|
|
|
|
- var orderData = {"img":data.img,"name":data.product.product_name,"goods_id":data.life_goods_id,"order":data.out_order_no,"price":this.$TOOL.disMoney(data.pay_money),"status":data.status};
|
|
|
|
|
- var resp = await this.sendMessageApi("order",orderData);
|
|
|
|
|
- if (!resp) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- this.sendMessageData({
|
|
|
|
|
- payload: {
|
|
|
|
|
- order: orderData
|
|
|
|
|
- },
|
|
|
|
|
- type: 'order'
|
|
|
|
|
- });
|
|
|
|
|
- },
|
|
|
|
|
- /**
|
|
|
|
|
- * 收集地址消息
|
|
|
|
|
- * @param data
|
|
|
|
|
- */
|
|
|
|
|
- async sendAddress(data){
|
|
|
|
|
- var orderData = {"img":data.img,"name":"完善会员信息","order":data.out_order_no,"status":0};
|
|
|
|
|
- var resp = await this.sendMessageApi("address",orderData);
|
|
|
|
|
- if (!resp) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- this.sendMessageData({
|
|
|
|
|
- payload: {
|
|
|
|
|
- address: orderData
|
|
|
|
|
- },
|
|
|
|
|
- type: 'address'
|
|
|
|
|
- });
|
|
|
|
|
- },
|
|
|
|
|
- async sendMessage(){
|
|
|
|
|
- if (!this.inputMessage) return ;
|
|
|
|
|
- var resp = await this.sendMessageApi("text",this.inputMessage);
|
|
|
|
|
- if (!resp) {
|
|
|
|
|
- this.inputMessage = "";
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- this.sendMessageData({
|
|
|
|
|
- payload: {
|
|
|
|
|
- text: this.inputMessage
|
|
|
|
|
- },
|
|
|
|
|
- type: 'text'
|
|
|
|
|
- });
|
|
|
|
|
- this.inputMessage = ""
|
|
|
|
|
- },
|
|
|
|
|
- sendMessageData({payload,type}){
|
|
|
|
|
- const message = {
|
|
|
|
|
- groupId: this.chatItem.poi_id,
|
|
|
|
|
- senderData: {
|
|
|
|
|
- avatar:this.chatItem.avatar
|
|
|
|
|
- },
|
|
|
|
|
- senderId: this.myid,
|
|
|
|
|
- messageId: Date.now(),
|
|
|
|
|
- payload: payload,
|
|
|
|
|
- timestamp: Date.now(),
|
|
|
|
|
- type: type,
|
|
|
|
|
- recalled: false,
|
|
|
|
|
- status: 'success',
|
|
|
|
|
- isHide: 0
|
|
|
|
|
- };
|
|
|
|
|
- this.pushList(message);
|
|
|
|
|
- },
|
|
|
|
|
- handleKeyCode(event){
|
|
|
|
|
- if (event.keyCode == 13) {
|
|
|
|
|
- if (!event.ctrlKey) {
|
|
|
|
|
- this.sendMessage()
|
|
|
|
|
- event.preventDefault();
|
|
|
|
|
- } else {
|
|
|
|
|
- this.inputMessage += "\n";
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- checkChatItem(index){
|
|
|
|
|
- this.checkChat = index;
|
|
|
|
|
- this.chatItem = this.chatContact[index]
|
|
|
|
|
- this.chatContact[index].last.num = 0;
|
|
|
|
|
- this.msgPage = 1;
|
|
|
|
|
- this.history.messages = []
|
|
|
|
|
- this.history.allLoaded = false
|
|
|
|
|
- this.orderData.list = [];
|
|
|
|
|
- this.orderData.page = 1;
|
|
|
|
|
- this.orderData.tab = "user";
|
|
|
|
|
- this.getMsgData();
|
|
|
|
|
- this.getMsgOrder();
|
|
|
|
|
- this.getOrderList();
|
|
|
|
|
- },
|
|
|
|
|
- async getMsgOrder(){
|
|
|
|
|
- var resp = await this.$API.chat.msgOrder.get({"msgId":this.chatItem.id})
|
|
|
|
|
- if (resp.code == 0) return ;
|
|
|
|
|
- this.msgOrder = resp.data.order;
|
|
|
|
|
- },
|
|
|
|
|
- initPush(){
|
|
|
|
|
- var _this = this;
|
|
|
|
|
- if (!this.pushObj) {
|
|
|
|
|
- this.pushObj = new Push({
|
|
|
|
|
- "url":this.wsUrl,
|
|
|
|
|
- "app_key":"265c33b73d5c04f918978577df2c48d2",
|
|
|
|
|
- "auth":this.wsAuth
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
- var user_channel = this.pushObj.subscribe('service-' + this.myid);
|
|
|
|
|
- user_channel.on('message', function (data) {
|
|
|
|
|
- _this.playAudio()
|
|
|
|
|
- _this.unreadCount ++;
|
|
|
|
|
- _this.sortItemData(data.item)
|
|
|
|
|
- if (_this.chatItem && _this.chatItem.openid == data.openid) { // 当前窗口实时推送
|
|
|
|
|
- _this.formatMsg(data);
|
|
|
|
|
- }
|
|
|
|
|
- // 给消息标红并更新最后一条消息
|
|
|
|
|
- var msgData = _this.chatContact;
|
|
|
|
|
- for (var i=0; i <= msgData.length;i ++) {
|
|
|
|
|
- var item = msgData[i];
|
|
|
|
|
- if (item && item.openid == data.openid) {
|
|
|
|
|
- item.last.type = data.type;
|
|
|
|
|
- item.last.content = data.content;
|
|
|
|
|
- item.last.create_at = data.create_at
|
|
|
|
|
- item.last.last_at = data.last_at
|
|
|
|
|
- // item.last.num ++;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- },
|
|
|
|
|
- truncateByBytes(str, maxBytes) {
|
|
|
|
|
- let count = 0;
|
|
|
|
|
- let result = '';
|
|
|
|
|
- for (const char of str) {
|
|
|
|
|
- // 中文、全角符号算 2 字节,其他算 1 字节
|
|
|
|
|
- const byteLen = char.match(/[^\x00-\xff]/) ? 2 : 1;
|
|
|
|
|
- if (count + byteLen > maxBytes) break;
|
|
|
|
|
- result += char;
|
|
|
|
|
- count += byteLen;
|
|
|
|
|
- }
|
|
|
|
|
- return result + (count < str.length ? '...' : '');
|
|
|
|
|
- },
|
|
|
|
|
- sortItemData(data){
|
|
|
|
|
- const existIdx = this.chatContact.findIndex(item => item.id === data.id);
|
|
|
|
|
- if (existIdx !== -1) { // 若已存在,按更新处理
|
|
|
|
|
- this.handleNewMessage(data);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- // 新增数据到最顶部
|
|
|
|
|
- this.chatContact.unshift(data);
|
|
|
|
|
- },
|
|
|
|
|
- handleNewMessage(updateData) {
|
|
|
|
|
- const idx = this.chatContact.findIndex(item => item.id === updateData.id);
|
|
|
|
|
- this.chatContact.splice(idx, 1, updateData);
|
|
|
|
|
- this.sortSessions();
|
|
|
|
|
- },
|
|
|
|
|
- sortSessions() {
|
|
|
|
|
- this.chatContact.sort((a, b) => {
|
|
|
|
|
- const timeA = a.last_at && a.last_at !== '-' ? new Date(a.last_at).getTime() : 0;
|
|
|
|
|
- const timeB = b.last_at && b.last_at !== '-' ? new Date(b.last_at).getTime() : 0;
|
|
|
|
|
- return timeB - timeA;
|
|
|
|
|
- });
|
|
|
|
|
- },
|
|
|
|
|
- sortBooks() {
|
|
|
|
|
- this.chatContact.sort((a, b) => b.last_at - a.last_at)
|
|
|
|
|
- },
|
|
|
|
|
- formatMsg(item){
|
|
|
|
|
- var payload = {};
|
|
|
|
|
- if (item.type == 'text') {
|
|
|
|
|
- payload.text = item.content
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'order') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.order = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'pay') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.pay = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'address') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.address = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'image') {
|
|
|
|
|
- payload = {
|
|
|
|
|
- contentType: 'image/png',
|
|
|
|
|
- name: 'uni-image.png',
|
|
|
|
|
- size: 82942,
|
|
|
|
|
- url: item.content,
|
|
|
|
|
- width: 2732,
|
|
|
|
|
- height: 2732,
|
|
|
|
|
- thumbnail: item.content
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
- const message = {
|
|
|
|
|
- groupId: item.poi_id,
|
|
|
|
|
- senderData: {
|
|
|
|
|
- avatar:item.source==2?item.avatar:item.user.avatar,
|
|
|
|
|
- name:item.source==2?item.nick.truename:item.user.nickname
|
|
|
|
|
- },
|
|
|
|
|
- senderId: (item.source==1?item.openid:item.service_id),
|
|
|
|
|
- messageId: item.msgId,
|
|
|
|
|
- payload: payload,
|
|
|
|
|
- timestamp: item.time,
|
|
|
|
|
- type: item.type,
|
|
|
|
|
- recalled: false,
|
|
|
|
|
- status: 'success',
|
|
|
|
|
- isHide: 0
|
|
|
|
|
- };
|
|
|
|
|
- this.pushList(message);
|
|
|
|
|
- },
|
|
|
|
|
- async pushList(message) {
|
|
|
|
|
- this.initMessageItem(message);
|
|
|
|
|
- this.history.messages.unshift(message);
|
|
|
|
|
- // 是否触发文字动效果
|
|
|
|
|
- if (message.type === 'text' || message.type === 'text_quote') {
|
|
|
|
|
- this.onSetText(message.payload.text);
|
|
|
|
|
- }
|
|
|
|
|
- // 缓存照片地址,
|
|
|
|
|
- if (message.type === 'image' || message.type === 'image_transmit') {
|
|
|
|
|
- imageList.push(message.payload.url);
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- // 组装item
|
|
|
|
|
- initMessageItem(message, index) {
|
|
|
|
|
- message['isHide'] = 0;
|
|
|
|
|
- if (index === 0 && (message.type === 'text' || message.type === 'text_quote')) {
|
|
|
|
|
- this.onSetText(message.payload.text);
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- // 文本触发效果相关========
|
|
|
|
|
- onSetText(text) {},
|
|
|
|
|
- // 切换聊天窗口
|
|
|
|
|
- async toggleChat() {
|
|
|
|
|
- this.visible = !this.visible
|
|
|
|
|
- if (this.visible) {
|
|
|
|
|
- // 打开窗口时清除未读角标
|
|
|
|
|
- this.unreadCount = 0
|
|
|
|
|
- }
|
|
|
|
|
- if (this.chatContact.length == 0) {
|
|
|
|
|
- this.loadMsg = true;
|
|
|
|
|
- var resp = await this.$API.chat.list.get({page:this.page,pageSize:this.size})
|
|
|
|
|
- this.loadMsg = false;
|
|
|
|
|
- if (resp.code == 0) {
|
|
|
|
|
- return this.$message.error(resp.msg)
|
|
|
|
|
- }
|
|
|
|
|
- this.chatContact = this.chatContact.concat(resp.data.rows)
|
|
|
|
|
- }
|
|
|
|
|
- // this.chatItem = this.chatContact[0]
|
|
|
|
|
- // this.userId = this.chatItem.openid;
|
|
|
|
|
- // this.getMsgData();
|
|
|
|
|
- },
|
|
|
|
|
- /**
|
|
|
|
|
- * 加载更多
|
|
|
|
|
- */
|
|
|
|
|
- async getMsgMore(){
|
|
|
|
|
- this.history.allLoaded = true;
|
|
|
|
|
- this.msgLoad = true;
|
|
|
|
|
- var resp = await this.$API.chat.msg.get({"page":this.msgPage,"size":this.msgSize,"openid":this.chatItem.openid})
|
|
|
|
|
- this.msgLoad = false;
|
|
|
|
|
- if (resp.data.rows.length > 0) {
|
|
|
|
|
- this.msgPage ++;
|
|
|
|
|
- var msgData = []
|
|
|
|
|
- var list = resp.data.rows
|
|
|
|
|
- // 同步混入数据
|
|
|
|
|
- list.forEach((item, ix) => {
|
|
|
|
|
- var payload = {};
|
|
|
|
|
- if (item.type == 'text') {
|
|
|
|
|
- payload.text = item.content
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'order') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.order = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'pay') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.pay = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'address') {
|
|
|
|
|
- var order = JSON.parse(item.content)
|
|
|
|
|
- payload.address = order
|
|
|
|
|
- }
|
|
|
|
|
- if (item.type == 'image') {
|
|
|
|
|
- payload = {
|
|
|
|
|
- contentType: 'image/png',
|
|
|
|
|
- name: 'uni-image.png',
|
|
|
|
|
- size: 82942,
|
|
|
|
|
- url: item.content,
|
|
|
|
|
- width: 2732,
|
|
|
|
|
- height: 2732,
|
|
|
|
|
- thumbnail: item.content
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
- const message = {
|
|
|
|
|
- groupId: item.poi_id,
|
|
|
|
|
- senderData: {
|
|
|
|
|
- avatar:item.avatar
|
|
|
|
|
- },
|
|
|
|
|
- senderId: (item.source==1?item.openid:item.service_id),
|
|
|
|
|
- messageId: item.msgId,
|
|
|
|
|
- payload: payload,
|
|
|
|
|
- timestamp: item.time,
|
|
|
|
|
- type: item.type,
|
|
|
|
|
- recalled: false,
|
|
|
|
|
- status: 'success',
|
|
|
|
|
- isHide: 0
|
|
|
|
|
- };
|
|
|
|
|
- msgData[ix] = message
|
|
|
|
|
- });
|
|
|
|
|
- this.history.messages = [...this.history.messages, ...msgData];
|
|
|
|
|
- this.history.allLoaded = false;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.history.allLoaded = true;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- /**
|
|
|
|
|
- * 首次加载
|
|
|
|
|
- */
|
|
|
|
|
- async getMsgData(){
|
|
|
|
|
- var resp = await this.$API.chat.msg.get({"page":this.msgPage,"size":this.msgSize,"openid":this.chatItem.openid})
|
|
|
|
|
- if (resp.data.rows.length > 0) {
|
|
|
|
|
- var msgData = resp.data.rows
|
|
|
|
|
- msgData.forEach((item,index)=>{
|
|
|
|
|
- this.formatMsg(item);
|
|
|
|
|
- })
|
|
|
|
|
- this.msgPage ++;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- async uploadSuccess(data){
|
|
|
|
|
- var resp = await this.sendMessageApi("image",data.data.src);
|
|
|
|
|
- if (!resp) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- this.sendMessageData({
|
|
|
|
|
- payload: {
|
|
|
|
|
- contentType: 'image/png',
|
|
|
|
|
- name: data.data.fileName,
|
|
|
|
|
- size: 0,
|
|
|
|
|
- url: data.data.src,
|
|
|
|
|
- width: 2732,
|
|
|
|
|
- height: 2732,
|
|
|
|
|
- thumbnail: data.data.src
|
|
|
|
|
- },
|
|
|
|
|
- type: 'image'
|
|
|
|
|
- });
|
|
|
|
|
- this.uploadImg = "";
|
|
|
|
|
- },
|
|
|
|
|
- async sendMessageApi(type,content){
|
|
|
|
|
- this.chatContact[this.checkChat].last.num = 0;
|
|
|
|
|
- var resp = await this.$API.chat.send.post({type:type,content: content,groupId: this.chatItem.poi_id,openid:this.chatItem.openid})
|
|
|
|
|
- if (resp.code == 0) return false;
|
|
|
|
|
- this.chatContact[this.checkChat].last.type = type;
|
|
|
|
|
- this.chatContact[this.checkChat].last.content = (type=='text'?this.truncateByBytes(content,18):content);
|
|
|
|
|
- this.chatContact[this.checkChat].last.create_at = resp.data.time;
|
|
|
|
|
- return true;
|
|
|
|
|
- },
|
|
|
|
|
- async getOrderList(){
|
|
|
|
|
- this.orderData.loading = true;
|
|
|
|
|
- var resp = await this.$API.order.list.get({"page":this.orderData.page,"pageSize":this.orderData.size,"order":this.orderData.order,"openid":this.chatItem.openid});
|
|
|
|
|
- this.orderData.loading = false;
|
|
|
|
|
- if (resp.code == 0) {
|
|
|
|
|
- return ;
|
|
|
|
|
- }
|
|
|
|
|
- this.orderData.list = resp.data.rows;
|
|
|
|
|
- this.orderData.total = resp.data.total;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style scoped lang="scss">
|
|
|
|
|
-@import '@/style/index.scss';
|
|
|
|
|
-
|
|
|
|
|
-.order-info-user{background-color: #fff;padding: 10px;margin-top: 10px;}
|
|
|
|
|
-.order-info-user .title{font-size: 16px;color: #333;font-weight: bold;padding-bottom: 10px;border-bottom: 1px solid #f8f8f8;}
|
|
|
|
|
-.order-info-user .info-item{height: 40px;line-height: 40px;font-size: 12px;display: flex;align-items: center;border-bottom: 1px solid #f8f8f8;}
|
|
|
|
|
-.order-info-user .info-item .right{color: #666;margin-left: auto;margin-right: 0;}
|
|
|
|
|
-.order-info-user .info-item .right text{border: 1px solid #ccc;color: #333;font-size: 12px;padding: 0 15upx;margin-left: 10px;border-radius: 5px;}
|
|
|
|
|
-
|
|
|
|
|
-.aside-tabs{display: flex;height: 65px;align-items: center;gap: 10px;border-bottom: 1px solid var(--el-border-color-light);padding: 13px 15px;}
|
|
|
|
|
-.aside-tabs .aside-tab-items{font-size: 14px;cursor: pointer;padding: 0 20px;}
|
|
|
|
|
-.aside-tabs .aside-tab-items.active{color: var(--el-color-primary);}
|
|
|
|
|
-.quick-search{display: flex;align-items: center;justify-content: space-between;gap: 10px;}
|
|
|
|
|
-.quick-search .search-input{flex: 1;display: flex;align-items: center;gap: 5px;}
|
|
|
|
|
-.quick-search .search-btn-txt{font-size: 14px;color: #409eff;cursor: pointer;}
|
|
|
|
|
-.quick-table .quick-table-body{margin: 10px 0;}
|
|
|
|
|
-.border-none{border: 0;}
|
|
|
|
|
-.msg-title{font-size: 18px;font-weight: bold;}
|
|
|
|
|
-.loading-text{background-color: #f8f8f8;text-align: center;font-size: 12px;}
|
|
|
|
|
-.order-list-chat{height: 100%;flex-direction: column;flex: 1;display: flex;}
|
|
|
|
|
-.m-order-s{background-color: #fff;border-radius: 5px;margin-bottom: 10px;border: 1px solid #f8f8f8;}
|
|
|
|
|
-.m-order-s .m-order-item{display: flex;font-size: 14px;position: relative;background-color: #f8f8f8;}
|
|
|
|
|
-.m-order-s .order-btn-group{display: flex;align-items: center;padding: 10px;gap: 10px;}
|
|
|
|
|
-.order-search-input{display: flex;align-items: center;gap: 10px;flex: 1;}
|
|
|
|
|
-.m-order-s .order-img{display: flex;}
|
|
|
|
|
-.m-order-s .order-img image{width: 80px;height: 80px;}
|
|
|
|
|
-.m-order-s .order-info {padding: 5px 10px 10px;flex: 1;}
|
|
|
|
|
-.m-order-s .order-info .title{font-size: 14px;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}
|
|
|
|
|
-.m-order-s .order-info .desc{font-size: 12px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;color: #999;}
|
|
|
|
|
-.m-order-s .order-info .price{font-size: 14px;color: #f00;}
|
|
|
|
|
-.m-order-s .order-status-btn{position: absolute;right: 0;bottom: 0;display: flex;align-items: center;gap: 5px;}
|
|
|
|
|
-.m-order-s .status{border-radius: 5px 0 5px 0;background-color: #909399;font-size: 12px;color: #fff;padding: 5px;}
|
|
|
|
|
-.m-order-s .status.cus{cursor: pointer;}
|
|
|
|
|
-.m-order-s .status.info{background-color: #909399;}
|
|
|
|
|
-.m-order-s .status.primary{background-color: #409eff;}
|
|
|
|
|
-.m-order-s .status.success{background-color: #67c23a;}
|
|
|
|
|
-.m-order-s .status.danger{background-color: #f56c6c;}
|
|
|
|
|
-.m-order-s .status.warn{background-color: #e6a23c;}
|
|
|
|
|
-
|
|
|
|
|
-.hideStr{overflow: hidden;width: 80%;}
|
|
|
|
|
-.contact-item{display: flex;align-items: center;background-color: #fff;padding: 10px;border-bottom: 1px solid #f8f8f8;cursor: pointer;}
|
|
|
|
|
-.contact-item.active{background-color: #f8f8f8;}
|
|
|
|
|
-.contact-item .img{position: relative;border: 1px solid #f8f8f8;border-radius: 5px;display: flex;align-items: center;justify-content: center;}
|
|
|
|
|
-.contact-item span.last-num{background-color: #f00;color: #fff;width: 20px;height: 20px;display: flex;align-items: center;justify-content: center;border-radius: 20px;font-size: 12px;margin-left: 10px;position: absolute;right: 0;top: 0;}
|
|
|
|
|
-
|
|
|
|
|
-.contact-item .kefu-store{margin-left: 10px;}
|
|
|
|
|
-.contact-item .kefu-store .name{font-size: 14px;color: #333;display: flex;align-items: center;}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-.contact-item .kefu-store .desc{font-size: 12px;color: #666;margin-top: 5px;}
|
|
|
|
|
-.contact-item .time{margin-left: auto;margin-right: 0;font-size: 12px;color: #666;}
|
|
|
|
|
-.send-btn-group{margin-top: 10px;display: flex;align-items: center;justify-content: space-between;}
|
|
|
|
|
-.send-btn-group .send-emoji{display: flex;align-items: center;gap: 15px;cursor: pointer;}
|
|
|
|
|
-.quick-group{display: flex;align-items: center;gap: 10px;padding: 15px 0;}
|
|
|
|
|
-.quick-group .item-btn{background-color: #f8f8f8;padding: 5px;border-radius: 3px;display: flex;align-items: center;gap: 5px;cursor: pointer;}
|
|
|
|
|
-.z_index2{position: relative;z-index: 2;}
|
|
|
|
|
-.empty-data{display: flex;width: 100%;text-align: center;justify-content: center;font-size: 18px;background-color: #f8f8f8;align-items: center;}
|
|
|
|
|
-.swiper-item-box {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
- box-sizing: border-box;
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- max-height: 300px;
|
|
|
|
|
- overflow: auto;
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- align-items: flex-start;
|
|
|
|
|
-
|
|
|
|
|
- .swiper-item-box-l {
|
|
|
|
|
- // width: calc(62.5vw);
|
|
|
|
|
- width: calc(100%);
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- align-items: flex-start;
|
|
|
|
|
- }
|
|
|
|
|
- .swiper-item-box-r {
|
|
|
|
|
- width: calc(37.5%);
|
|
|
|
|
- flex-wrap: wrap;
|
|
|
|
|
- align-items: flex-start;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .emoji-item {
|
|
|
|
|
- width: calc(12.5%);
|
|
|
|
|
- height: calc(12.5%);
|
|
|
|
|
- flex-shrink: 0;
|
|
|
|
|
- transition: all 0.1s;
|
|
|
|
|
- padding: 10px 0;
|
|
|
|
|
-
|
|
|
|
|
- .img {
|
|
|
|
|
- width: 55%;
|
|
|
|
|
- height: 55%;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- }
|
|
|
|
|
- &:hover {
|
|
|
|
|
- background-color: #f8f8f8;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.flex_r {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: row;
|
|
|
|
|
-}
|
|
|
|
|
-.swiper-item-box-b {
|
|
|
|
|
- width: calc(38%);
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- z-index: 99;
|
|
|
|
|
- right: 0rpx;
|
|
|
|
|
- bottom: 0px;
|
|
|
|
|
- padding: 0 0 40rpx 0;
|
|
|
|
|
- // background-color: #000;
|
|
|
|
|
- background-image: linear-gradient(to top, #ececec, #ececec, #ececec, #ececec, #ececec, rgba(0, 0, 0, 0));
|
|
|
|
|
-}
|
|
|
|
|
-.swiper-item-box-delete {
|
|
|
|
|
- width: 116rpx;
|
|
|
|
|
- height: calc(12.5%);
|
|
|
|
|
- border-radius: 10rpx;
|
|
|
|
|
- margin-right: 20rpx;
|
|
|
|
|
- background-color: #fff;
|
|
|
|
|
- .img {
|
|
|
|
|
- width: 45%;
|
|
|
|
|
- height: 45%;
|
|
|
|
|
- margin-right: 4rpx;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.swiper-item-box-button {
|
|
|
|
|
- width: 116rpx;
|
|
|
|
|
- height: calc(12.5vw);
|
|
|
|
|
- border-radius: 10rpx;
|
|
|
|
|
- margin-right: 10rpx;
|
|
|
|
|
- background-color: #05c160;
|
|
|
|
|
-}
|
|
|
|
|
-.page {
|
|
|
|
|
- position: fixed;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- bottom: 0;
|
|
|
|
|
- right: 0;
|
|
|
|
|
- background-color: #ededed;
|
|
|
|
|
-}
|
|
|
|
|
-.scroll-Y {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 0;
|
|
|
|
|
- transition: all 0.2s;
|
|
|
|
|
- transform: rotate(180deg);
|
|
|
|
|
- background-color: #ededed;
|
|
|
|
|
- ::-webkit-scrollbar {
|
|
|
|
|
- display: none;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.scroll-view-str {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.message-list .time {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- color: #a3a3a3;
|
|
|
|
|
- line-height: 50px;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-.message-list .recalled {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 50rpx;
|
|
|
|
|
- margin: 20rpx 0;
|
|
|
|
|
- color: #a3a3a3;
|
|
|
|
|
-
|
|
|
|
|
- .recalled-edit {
|
|
|
|
|
- color: #5a6693;
|
|
|
|
|
- margin-left: 14rpx;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-@keyframes simple-blink {
|
|
|
|
|
- 0%, 100% { opacity: 1; }
|
|
|
|
|
- 50% { opacity: 0; }
|
|
|
|
|
-}
|
|
|
|
|
-.global-im {
|
|
|
|
|
- .unreadCount{
|
|
|
|
|
- position: fixed;
|
|
|
|
|
- right: 42px;
|
|
|
|
|
- bottom: 162px;
|
|
|
|
|
- animation: simple-blink 2s ease-in-out infinite;
|
|
|
|
|
- }
|
|
|
|
|
- .im-trigger {
|
|
|
|
|
- position: fixed;
|
|
|
|
|
- right: 24px;
|
|
|
|
|
- bottom: 124px;
|
|
|
|
|
- width: 48px;
|
|
|
|
|
- height: 48px;
|
|
|
|
|
- background: #409eff;
|
|
|
|
|
- border-radius: 50%;
|
|
|
|
|
- display: flex;
|
|
|
|
|
- align-items: center;
|
|
|
|
|
- justify-content: center;
|
|
|
|
|
- cursor: pointer;
|
|
|
|
|
- box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
|
|
|
|
- z-index: 2000;
|
|
|
|
|
- transition: all 0.3s;
|
|
|
|
|
- color: white;
|
|
|
|
|
- &:hover {
|
|
|
|
|
- background: #66b1ff;
|
|
|
|
|
- }
|
|
|
|
|
- &.active {
|
|
|
|
|
- background: #909399;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.chat-container {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- .message-list {
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- overflow-y: auto;
|
|
|
|
|
- background-color: #f8f8f8;
|
|
|
|
|
- transition: all 0.2s;
|
|
|
|
|
- transform: rotate(180deg);
|
|
|
|
|
- .message-item {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- margin-bottom: 16px;
|
|
|
|
|
- &.self {
|
|
|
|
|
- flex-direction: row-reverse;
|
|
|
|
|
- .content {
|
|
|
|
|
- margin-right: 12px;
|
|
|
|
|
- align-items: flex-end;
|
|
|
|
|
- .text {
|
|
|
|
|
- background: #95ec69;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- &.other {
|
|
|
|
|
- .content {
|
|
|
|
|
- margin-left: 12px;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- .content {
|
|
|
|
|
- display: flex;
|
|
|
|
|
- flex-direction: column;
|
|
|
|
|
- max-width: 70%;
|
|
|
|
|
- .name {
|
|
|
|
|
- font-size: 12px;
|
|
|
|
|
- color: #999;
|
|
|
|
|
- margin-bottom: 4px;
|
|
|
|
|
- }
|
|
|
|
|
- .text {
|
|
|
|
|
- padding: 8px 12px;
|
|
|
|
|
- background: #f0f0f0;
|
|
|
|
|
- border-radius: 12px;
|
|
|
|
|
- word-break: break-all;
|
|
|
|
|
- }
|
|
|
|
|
- .time {
|
|
|
|
|
- font-size: 10px;
|
|
|
|
|
- color: #ccc;
|
|
|
|
|
- margin-top: 4px;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- .input-area {
|
|
|
|
|
- padding: 0 16px 16px 16px;
|
|
|
|
|
- border-top: 1px solid #eee;
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|