IM功能
parent
6baf1534c1
commit
5e38247ce8
|
@ -0,0 +1,67 @@
|
||||||
|
import { http,Method } from "@/utils/request.js";
|
||||||
|
|
||||||
|
import api from "@/config/api.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聊天详情接口
|
||||||
|
* @param {*} talkId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getTalk(talkId) {
|
||||||
|
return http.request({
|
||||||
|
url: `${api.im}/talk/${talkId}`,
|
||||||
|
method: Method.GET,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取与用户的聊天详情
|
||||||
|
* @param {*} talkId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getTalkByUser(userId) {
|
||||||
|
return http.request({
|
||||||
|
url: `${api.im}/talk/by/user/${userId}`,
|
||||||
|
method: Method.GET,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聊天列表
|
||||||
|
* @param {*} talkId
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getTalkList(params) {
|
||||||
|
return http.request({
|
||||||
|
url: `${api.im}/talk/list`,
|
||||||
|
method: Method.GET,
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聊天信息接口
|
||||||
|
* @param {*} params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getTalkMessage(params) {
|
||||||
|
return http.request({
|
||||||
|
url: `${api.im}/message`,
|
||||||
|
method: Method.GET,
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取聊天信息接口
|
||||||
|
* @param {*} params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function cleanUnreadMessage(params) {
|
||||||
|
return http.request({
|
||||||
|
url: `${api.im}/message/clean/unred`,
|
||||||
|
method: Method.PUT,
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
*/
|
*/
|
||||||
// 开发环境
|
// 开发环境
|
||||||
const dev = {
|
const dev = {
|
||||||
common: "https://common-api.pickmall.cn",
|
common: "http://192.168.0.113:8890",
|
||||||
buyer: "https://buyer-api.pickmall.cn",
|
buyer: "http://192.168.0.113:8898",
|
||||||
|
im: "http://192.168.0.113:8885",
|
||||||
|
|
||||||
|
// common: "https://common-api.pickmall.cn",
|
||||||
|
// buyer: "https://buyer-api.pickmall.cn",
|
||||||
};
|
};
|
||||||
// 生产环境
|
// 生产环境
|
||||||
const prod = {
|
const prod = {
|
||||||
|
@ -28,6 +32,7 @@ api = prod;
|
||||||
|
|
||||||
api.buyer += "/buyer";
|
api.buyer += "/buyer";
|
||||||
api.common += "/common";
|
api.common += "/common";
|
||||||
|
api.im += "/im";
|
||||||
export default {
|
export default {
|
||||||
...api,
|
...api,
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,8 @@ export default {
|
||||||
logo: "https://lilishop-oss.oss-cn-beijing.aliyuncs.com/4c864e133c2944efad1f7282ac8a3b9e.png", //logo地址
|
logo: "https://lilishop-oss.oss-cn-beijing.aliyuncs.com/4c864e133c2944efad1f7282ac8a3b9e.png", //logo地址
|
||||||
customerServiceMobile: "13161366885", //客服电话
|
customerServiceMobile: "13161366885", //客服电话
|
||||||
customerServiceEmail: "lili@lili.com", //客服邮箱
|
customerServiceEmail: "lili@lili.com", //客服邮箱
|
||||||
imWebSrc: "https://im.pickmall.cn", //IM地址
|
imWebSrc: "http://192.168.0.113:8001/", //IM地址
|
||||||
|
BASE_WS_URL: "ws://192.168.0.113:8885/lili/webSocket",
|
||||||
enableGetClipboard: true, //是否启用粘贴板获取 scanAuthNavigation 中的链接,如果匹配则会跳转到对应页面
|
enableGetClipboard: true, //是否启用粘贴板获取 scanAuthNavigation 中的链接,如果匹配则会跳转到对应页面
|
||||||
enableMiniBarStartUpApp: true, //是否在h5中右侧浮空按钮点击启动app
|
enableMiniBarStartUpApp: true, //是否在h5中右侧浮空按钮点击启动app
|
||||||
/**
|
/**
|
||||||
|
|
20
pages.json
20
pages.json
|
@ -274,8 +274,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "im/index",
|
||||||
|
"style": {
|
||||||
|
"app-plus": {
|
||||||
|
},
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"navigationStyle": "custom" // 隐藏系统导航栏
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "im/list",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom", // 隐藏系统导航栏
|
||||||
|
"enablePullDownRefresh": true,
|
||||||
|
"app-plus": {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "set/feedBack",
|
"path": "set/feedBack",
|
||||||
"style": {
|
"style": {
|
||||||
|
@ -434,6 +451,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,530 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<u-navbar class="my-title" title-size="32" back-text="" :title="toUser.name"></u-navbar>
|
||||||
|
<!-- 空盒子用来防止消息过少时 拉起键盘会遮盖消息 -->
|
||||||
|
<view :animation="anData" style="height:0;">
|
||||||
|
</view>
|
||||||
|
<!-- 消息体 -->
|
||||||
|
<!-- 用来获取消息体高度 -->
|
||||||
|
<view id="msgList">
|
||||||
|
<!-- 消息 -->
|
||||||
|
<view class="flex-column-start" v-for="(item, index) in msgList" :key="index">
|
||||||
|
<view class="flex-row-start column-time">
|
||||||
|
<view v-show="compareTime(index, item.createTime)" class="flex-row-start date-text"
|
||||||
|
v-text="beautifyTime(item.createTime)">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 用户消息 头像可选加入-->
|
||||||
|
<view v-if="item.my" class="flex justify-end padding-right one-show align-start padding-top">
|
||||||
|
<!-- <image class="chat-img flex-row-center" :src="'https://ikeeppet.oss-cn-zhangjiakou.aliyuncs.com/028b7818b78c47ef8f87a7faa1098faf.jpg'" mode="aspectFill" ></image> -->
|
||||||
|
|
||||||
|
<view class="flex justify-end" style="width: 400rpx;margin-top: 12px;">
|
||||||
|
<view>
|
||||||
|
<view class="user-name">{{ user.nickName }}</view>
|
||||||
|
<view class="margin-left padding-chat bg-user-orang" style="border-radius: 35rpx;">
|
||||||
|
<text style="word-break: break-all;">{{ item.text }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-avatar :src="user.face" :text="user.face ? '' : user.name" bg-color="#DDDDDD"></u-avatar>
|
||||||
|
<!-- <u-image class="chat-img margin-left" style="height: 100rpx;width: 100rpx;" shape="circle"
|
||||||
|
:src="user.face || 'https://avatars.dicebear.com/api/initials/' + user.nickName + '.svg?fontSize=38'"
|
||||||
|
mode="aspectFill"></u-image> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<!-- 接收人消息 -->
|
||||||
|
<view v-else class="flex-row-start margin-left margin-top one-show">
|
||||||
|
<view class="chat-img flex-row-center">
|
||||||
|
<u-avatar :src="toUser.face" :text="toUser.face ? '' : toUser.name"
|
||||||
|
bg-color="#DDDDDD"></u-avatar>
|
||||||
|
<!-- <u-image style="height: 100rpx;width: 100rpx;" shape="circle"
|
||||||
|
:src="toUser.face || 'https://avatars.dicebear.com/api/initials/' + toUser.name + '.svg?fontSize=38'"
|
||||||
|
mode="aspectFit"></u-image> -->
|
||||||
|
</view>
|
||||||
|
<view class="flex" style="width: 500rpx;">
|
||||||
|
<view>
|
||||||
|
<view class="other-name">{{ toUser.name }}</view>
|
||||||
|
<view class="margin-left padding-chat flex-column-start bg-to-color"
|
||||||
|
style="border-radius: 35rpx;">
|
||||||
|
<text style="word-break: break-all;">{{ item.text }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- loading是显示 -->
|
||||||
|
<view v-show="msgLoad" class="flex-row-start margin-left margin-top">
|
||||||
|
<view class="chat-img flex-row-center">
|
||||||
|
<!-- <image style="height: 75rpx;width: 75rpx;" src="../../static/image/robt.png" mode="aspectFit"></image> -->
|
||||||
|
</view>
|
||||||
|
<view class="flex" style="width: 500rpx;">
|
||||||
|
<view class="margin-left padding-chat flex-column-start"
|
||||||
|
style="border-radius: 35rpx;background-color: #f9f9f9;">
|
||||||
|
<view class="cuIcon-loading turn-load" style="font-size: 35rpx;color: #3e9982;">
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 防止消息底部被遮 -->
|
||||||
|
<view style="height: 120rpx;">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 底部导航栏 -->
|
||||||
|
<view class="flex-column-center" style="position: fixed;bottom: -180px;" :animation="animationData">
|
||||||
|
<view class="bottom-dh-char flex-row-around" style="font-size: 55rpx;">
|
||||||
|
<!-- vue无法使用软键盘"发送" -->
|
||||||
|
<input v-model="msg" class="dh-input" type="text" style="background-color: #f0f0f0;" @confirm="sendMsg"
|
||||||
|
confirm-type="search" placeholder-class="my-neirong-sm" placeholder="用一句简短的话描述您的问题" />
|
||||||
|
<view @click="sendMsg" class="cu-tag bg-cyan round">
|
||||||
|
发送
|
||||||
|
</view>
|
||||||
|
<!-- <text @click="ckAdd" class="cuIcon-roundaddfill text-brown"></text> -->
|
||||||
|
</view>
|
||||||
|
<!-- 附加栏(自定义) -->
|
||||||
|
<view class="box-normal flex-row-around flex-wrap">
|
||||||
|
<view class="tb-text">
|
||||||
|
<view class="cuIcon-form"></view>
|
||||||
|
<text>问题反馈</text>
|
||||||
|
</view>
|
||||||
|
<view class="tb-text">
|
||||||
|
<view class="cuIcon-form"></view>
|
||||||
|
<text>人工客服</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// rpx和px的比率
|
||||||
|
var l
|
||||||
|
// 可用窗口高度
|
||||||
|
var wh
|
||||||
|
// 顶部空盒子的高度
|
||||||
|
var mgUpHeight
|
||||||
|
import { getTalkMessage, getTalkByUser } from "@/api/im.js";
|
||||||
|
import SocketService from "@/utils/socket_service.js";
|
||||||
|
import storage from "@/utils/storage.js";
|
||||||
|
import { beautifyTime } from "@/utils/filters.js"
|
||||||
|
export default {
|
||||||
|
onLoad(options) {
|
||||||
|
// 如果需要缓存消息缓存msgList即可
|
||||||
|
// 监听键盘拉起
|
||||||
|
// 因为无法控制键盘拉起的速度,所以这里尽量以慢速处理
|
||||||
|
uni.onKeyboardHeightChange(res => {
|
||||||
|
const query = uni.createSelectorQuery()
|
||||||
|
query.select('#msgList').boundingClientRect(data => {
|
||||||
|
// 若消息体没有超过2倍的键盘则向下移动差值,防止遮住消息体
|
||||||
|
var up = res.height * 2 - data.height - l * 110
|
||||||
|
console.log(up)
|
||||||
|
if (up > 0) {
|
||||||
|
// 动态改变空盒子高度
|
||||||
|
this.msgMove(up, 300)
|
||||||
|
// 记录改变的值,若不收回键盘且发送了消息用来防止消息过多被遮盖
|
||||||
|
mgUpHeight = up
|
||||||
|
}
|
||||||
|
// 收回
|
||||||
|
if (res.height == 0) {
|
||||||
|
this.msgMove(0, 0)
|
||||||
|
}
|
||||||
|
}).exec();
|
||||||
|
})
|
||||||
|
var query = uni.getSystemInfoSync()
|
||||||
|
|
||||||
|
l = query.screenWidth / 750
|
||||||
|
wh = query.windowHeight
|
||||||
|
this.srcollHeight = (query.windowHeight - 44) + "px"
|
||||||
|
this.user = storage.getUserInfo()
|
||||||
|
this.toUser = storage.getTalkToUser()
|
||||||
|
|
||||||
|
if (options.talkId) {
|
||||||
|
this.params.talkId = options.talkId;
|
||||||
|
this.getTalkMessage()
|
||||||
|
} else {
|
||||||
|
this.getTalk(options.userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ws.connect();
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.params.pageNumber = this.params.pageNumber + 1
|
||||||
|
this.getTalkMessage()
|
||||||
|
console.log('下拉事件');
|
||||||
|
setTimeout(function () {
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
beautifyTime
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
msgLoad: false,
|
||||||
|
anData: {},
|
||||||
|
animationData: {},
|
||||||
|
msgList: [],
|
||||||
|
oldHeight: 0,
|
||||||
|
params: { //搜索条件
|
||||||
|
talkId: '',
|
||||||
|
pageSize: 10,
|
||||||
|
pageNumber: 1,
|
||||||
|
},
|
||||||
|
goToIndex: 0, // 前往位置
|
||||||
|
msg: "",
|
||||||
|
go: 0,
|
||||||
|
newMessageNum: 0,
|
||||||
|
user: {},
|
||||||
|
toUser: {},
|
||||||
|
srcollHeight: 0,
|
||||||
|
ws: new SocketService(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'ws.callBackMapping': {
|
||||||
|
handler: function (val) {
|
||||||
|
val = JSON.parse(val)
|
||||||
|
if (val.messageResultType == 'MESSAGE') {
|
||||||
|
this.msgList.push(val.result)
|
||||||
|
}
|
||||||
|
this.newMessageNum++;
|
||||||
|
console.log(this.msgList)
|
||||||
|
//接收到消息后发送已读
|
||||||
|
let msg = val
|
||||||
|
msg.operation_type = 'READ'
|
||||||
|
this.ws.send(JSON.stringify(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
beautifyTime,
|
||||||
|
// 切换输入法时移动输入框(按照官方的上推页面的原理应该会自动适应不同的键盘高度-->官方bug)
|
||||||
|
goPag(kh) {
|
||||||
|
this.upTowmn(0, 250)
|
||||||
|
if (this.keyHeight != 0) {
|
||||||
|
if (kh - this.keyHeight > 0) {
|
||||||
|
this.upTowmn(this.keyHeight - kh, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 移动顶部的空盒子
|
||||||
|
msgMove(x, t) {
|
||||||
|
var animation = uni.createAnimation({
|
||||||
|
duration: t,
|
||||||
|
timingFunction: 'linear',
|
||||||
|
})
|
||||||
|
|
||||||
|
this.animation = animation
|
||||||
|
|
||||||
|
animation.height(x).step()
|
||||||
|
|
||||||
|
this.anData = animation.export()
|
||||||
|
},
|
||||||
|
// 保持消息体可见
|
||||||
|
msgGo(type) {
|
||||||
|
const query = uni.createSelectorQuery()
|
||||||
|
// 延时100ms保证是最新的高度
|
||||||
|
setTimeout(() => {
|
||||||
|
// 获取消息体高度
|
||||||
|
query.select('#msgList').boundingClientRect(data => {
|
||||||
|
|
||||||
|
// 如果超过scorll高度就滚动scorll
|
||||||
|
if (type == 'up') {
|
||||||
|
this.go = data.height - this.oldHeight
|
||||||
|
} else if (type == 'down') {
|
||||||
|
this.go = data.height - wh + 120
|
||||||
|
}
|
||||||
|
// if (this.oldHeight > 0) {
|
||||||
|
// this.go = data.height - this.oldHeight
|
||||||
|
// } else {
|
||||||
|
// // if (data.height - (wh - 32) > 0) {
|
||||||
|
// this.go = data.height - wh + 120
|
||||||
|
// }
|
||||||
|
// 保证键盘第一次拉起时消息体能保持可见
|
||||||
|
var moveY = wh - data.height
|
||||||
|
// 超出页面则缩回空盒子
|
||||||
|
if (moveY - mgUpHeight < 0) {
|
||||||
|
// 小于0则视为0
|
||||||
|
if (moveY < 0) {
|
||||||
|
this.msgMove(0, 200)
|
||||||
|
} else {
|
||||||
|
// 否则缩回盒子对应的高度
|
||||||
|
this.msgMove(moveY, 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: this.go,
|
||||||
|
duration: 0
|
||||||
|
})
|
||||||
|
this.oldHeight = data.height
|
||||||
|
}).exec();
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
|
// 回答问题的业务逻辑
|
||||||
|
answer(id) {
|
||||||
|
// 这里应该传入问题的id,模拟就用index代替了
|
||||||
|
console.log(id)
|
||||||
|
|
||||||
|
},
|
||||||
|
sendMsg() {
|
||||||
|
console.log("发送")
|
||||||
|
// 消息为空不做任何操作
|
||||||
|
if (this.msg == "") {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// 显示消息 msg消息文本,my鉴别是谁发的消息(不能用俩个消息数组循环,否则消息不会穿插)
|
||||||
|
let msg = {
|
||||||
|
operation_type: "MESSAGE",
|
||||||
|
to: this.toUser.userId,
|
||||||
|
from: this.user.id,
|
||||||
|
message_type: "MESSAGE",
|
||||||
|
context: this.msg,
|
||||||
|
talk_id: this.params.talkId,
|
||||||
|
}
|
||||||
|
this.ws.send(JSON.stringify(msg))
|
||||||
|
this.msgList.push({ "text": this.msg, "my": true })
|
||||||
|
// 保证消息可见
|
||||||
|
let type = 'down';
|
||||||
|
this.msgGo(type)
|
||||||
|
// 回答问题
|
||||||
|
// this.msgKf(this.msg)
|
||||||
|
// 清除消息
|
||||||
|
this.msg = ""
|
||||||
|
},
|
||||||
|
// msgKf(x) {
|
||||||
|
// // loading
|
||||||
|
// // this.msgLoad = true
|
||||||
|
// // 这里连接服务器获取答案
|
||||||
|
|
||||||
|
// // 下面模拟请求
|
||||||
|
// // setTimeout(() => {
|
||||||
|
// // // 取消loading
|
||||||
|
// // this.msgLoad = false
|
||||||
|
// // // this.msgGo()
|
||||||
|
// // }, 2000)
|
||||||
|
// },
|
||||||
|
// 不建议输入框聚焦时操作此动画
|
||||||
|
ckAdd() {
|
||||||
|
if (!this.showTow) {
|
||||||
|
this.upTowmn(-180, 350)
|
||||||
|
} else {
|
||||||
|
this.upTowmn(0, 200)
|
||||||
|
}
|
||||||
|
this.showTow = !this.showTow
|
||||||
|
},
|
||||||
|
hideKey() {
|
||||||
|
uni.hideKeyboard()
|
||||||
|
},
|
||||||
|
// 拉起/收回附加栏
|
||||||
|
upTowmn(x, t) {
|
||||||
|
|
||||||
|
var animation = uni.createAnimation({
|
||||||
|
duration: t,
|
||||||
|
timingFunction: 'ease',
|
||||||
|
})
|
||||||
|
|
||||||
|
this.animation = animation
|
||||||
|
|
||||||
|
animation.translateY(x).step()
|
||||||
|
|
||||||
|
this.animationData = animation.export()
|
||||||
|
},
|
||||||
|
async getTalkMessage() {
|
||||||
|
let type = '';
|
||||||
|
await getTalkMessage(this.params).then(res => {
|
||||||
|
if (res.data.success) {
|
||||||
|
if (this.msgList.length >= 10) {
|
||||||
|
this.msgList.unshift(...res.data.result)
|
||||||
|
type = 'up'
|
||||||
|
} else {
|
||||||
|
this.msgList = res.data.result
|
||||||
|
type = 'down'
|
||||||
|
}
|
||||||
|
this.msgList.forEach(item => {
|
||||||
|
if (item.fromUser === this.user.id) {
|
||||||
|
item.my = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.msgGo(type)
|
||||||
|
},
|
||||||
|
touchmovemsg(e) {
|
||||||
|
if (e.target.scrollTop == 0) {
|
||||||
|
this.params.pageNumber = this.params.pageNumber + 1
|
||||||
|
this.getTalkMessage()
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
async getTalk(userId) {
|
||||||
|
getTalkByUser(userId).then(res => {
|
||||||
|
if (res.data.success) {
|
||||||
|
this.toUser = res.data.result
|
||||||
|
this.params.talkId = res.data.result.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理消息时间是否显示
|
||||||
|
compareTime(index, datetime) {
|
||||||
|
if (datetime == undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof datetime == "number") {
|
||||||
|
datetime = this.unixToDate(datetime, "yyyy-MM-dd hh:mm");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.msgList[index].is_revoke == 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime = datetime.replace(/-/g, "/");
|
||||||
|
let time = Math.floor(Date.parse(datetime) / 1000);
|
||||||
|
let currTime = Math.floor(new Date().getTime() / 1000);
|
||||||
|
|
||||||
|
// 当前时间5分钟内时间不显示
|
||||||
|
if (currTime - time < 300) return false;
|
||||||
|
// 判断是否是最后一条消息,最后一条消息默认显示时间
|
||||||
|
if (index == this.msgList.length - 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
let nextDate
|
||||||
|
if (this.msgList[index + 1]) {
|
||||||
|
nextDate = this.msgList[index + 1].createTime.replace(/-/g, "/");
|
||||||
|
if (nextDate - datetime < 300) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(
|
||||||
|
this.unixToDate(new Date(datetime), "{y}-{m}-{d} {h}:{i}") ==
|
||||||
|
this.unixToDate(new Date(nextDate), "{y}-{m}-{d} {h}:{i}")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将unix时间戳转换为指定格式
|
||||||
|
* @param unix 时间戳【秒】
|
||||||
|
* @param format 转换格式
|
||||||
|
* @returns {*|string}
|
||||||
|
*/
|
||||||
|
unixToDate(unix, format) {
|
||||||
|
if (!unix) return unix;
|
||||||
|
let _format = format || "yyyy-MM-dd hh:mm:ss";
|
||||||
|
const d = new Date(unix);
|
||||||
|
const o = {
|
||||||
|
"M+": d.getMonth() + 1,
|
||||||
|
"d+": d.getDate(),
|
||||||
|
"h+": d.getHours(),
|
||||||
|
"m+": d.getMinutes(),
|
||||||
|
"s+": d.getSeconds(),
|
||||||
|
"q+": Math.floor((d.getMonth() + 3) / 3),
|
||||||
|
S: d.getMilliseconds(),
|
||||||
|
};
|
||||||
|
if (/(y+)/.test(_format))
|
||||||
|
_format = _format.replace(
|
||||||
|
RegExp.$1,
|
||||||
|
(d.getFullYear() + "").substr(4 - RegExp.$1.length)
|
||||||
|
);
|
||||||
|
for (const k in o)
|
||||||
|
if (new RegExp("(" + k + ")").test(_format))
|
||||||
|
_format = _format.replace(
|
||||||
|
RegExp.$1,
|
||||||
|
RegExp.$1.length === 1
|
||||||
|
? o[k]
|
||||||
|
: ("00" + o[k]).substr(("" + o[k]).length)
|
||||||
|
);
|
||||||
|
return _format;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bottom-dh-char {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
width: 750rpx;
|
||||||
|
height: 110rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #737373;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-name {
|
||||||
|
text-align: left;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #737373;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-time {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-box {
|
||||||
|
width: 720rpx;
|
||||||
|
padding-left: 25rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hui-box {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dh-input {
|
||||||
|
width: 500rpx;
|
||||||
|
height: 65rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
padding-left: 15rpx;
|
||||||
|
font-size: 35rpx;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-normal {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 180px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-text view {
|
||||||
|
font-size: 65rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-text text {
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #737373;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-img {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.padding-chat {
|
||||||
|
padding: 17rpx 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-nv {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "./index-app.scss";
|
||||||
|
</style>
|
|
@ -0,0 +1,229 @@
|
||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<u-navbar class="my-title" title-size="32" back-text="" :title="'消息(' + talkList.length + ')'"></u-navbar>
|
||||||
|
<scroll-view class="list-scroll-content" scroll-y @scrolltolower="loadData(tabIndex)">
|
||||||
|
<!-- 空白页 -->
|
||||||
|
<u-empty text="暂无信息" mode="list" v-if="talkList.length === 0"></u-empty>
|
||||||
|
<!-- 消息列表 -->
|
||||||
|
<!-- 我的订单,代付款 -->
|
||||||
|
<div class="iconBox">
|
||||||
|
<view class="icon-list">
|
||||||
|
<view class="icon-item" @click="cleanUnread()">
|
||||||
|
<div class="bag bag1">
|
||||||
|
<u-icon name="trash" size="50" color="#fff"></u-icon>
|
||||||
|
</div>
|
||||||
|
<view>清除未读</view>
|
||||||
|
</view>
|
||||||
|
<view class="icon-item" @click="navigateTo('/pages/tabbar/home/title')">
|
||||||
|
<div class="bag bag2">
|
||||||
|
<u-icon name="bell" size="50" color="#fff"></u-icon>
|
||||||
|
</div>
|
||||||
|
<view>系统消息</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</div>
|
||||||
|
<u-search class="nav-search" v-model="userName" clearabled @change="getList()" placeholder="搜索用户"
|
||||||
|
:show-action="false"></u-search>
|
||||||
|
<view class="talk-view" :key="index" v-for="(item, index) in talkList">
|
||||||
|
<view>
|
||||||
|
<view @click="onclickToTalkInfo(item)">
|
||||||
|
<view class="talk-item-view">
|
||||||
|
<view class="talk-img">
|
||||||
|
<u-avatar :src="item.face" :text="item.face ? '' : item.name" bg-color="#DDDDDD"></u-avatar>
|
||||||
|
</view>
|
||||||
|
<view class="talk-info">
|
||||||
|
<view class="talk-name u-line-2">{{ item.name }}
|
||||||
|
<u-tag class="talk-tag" size="mini" text="店铺" type="warning" v-if="item.storeFlag" />
|
||||||
|
</view>
|
||||||
|
<view class="talk-message">
|
||||||
|
{{ item.lastTalkMessage }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="talk-time">
|
||||||
|
<view>
|
||||||
|
{{ beautifyTime(item.lastTalkTime) }}
|
||||||
|
</view>
|
||||||
|
<view>
|
||||||
|
<u-badge type="error" absolute :offset="[45, 20]" :count="item.unread"></u-badge>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getTalkList } from "@/api/im.js";
|
||||||
|
import storage from "@/utils/storage.js";
|
||||||
|
import { beautifyTime } from "@/utils/filters.js"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
count: {
|
||||||
|
loadStatus: "more",
|
||||||
|
},
|
||||||
|
talkList: [], //聊天列表
|
||||||
|
userName: '',
|
||||||
|
pointData: {}, //累计获取 未输入 集合
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
beautifyTime
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
this.getList()
|
||||||
|
console.log('下拉事件');
|
||||||
|
setTimeout(function () {
|
||||||
|
uni.stopPullDownRefresh();
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 触底加载
|
||||||
|
*/
|
||||||
|
onReachBottom() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
beautifyTime,
|
||||||
|
onclickToTalkInfo(val) {
|
||||||
|
storage.setTalkToUser(val)
|
||||||
|
uni.navigateTo({
|
||||||
|
url:
|
||||||
|
"/pages/mine/im/index?talkId=" + val.id,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 获取聊天列表
|
||||||
|
*/
|
||||||
|
getList() {
|
||||||
|
let params = {
|
||||||
|
userName: this.userName,
|
||||||
|
}
|
||||||
|
uni.showLoading({
|
||||||
|
title: "加载中",
|
||||||
|
});
|
||||||
|
getTalkList(params).then((res) => {
|
||||||
|
uni.hideLoading();
|
||||||
|
if (res.data.success) {
|
||||||
|
this.talkList = res.data.result;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
navigateTo(url) {
|
||||||
|
uni.navigateTo({
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
cleanUnread(){
|
||||||
|
|
||||||
|
},
|
||||||
|
search() {
|
||||||
|
|
||||||
|
},
|
||||||
|
// clear() {
|
||||||
|
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.talk-view {
|
||||||
|
border-radius: 20rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
.talk-item-view {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
|
||||||
|
.talk-img {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-info {
|
||||||
|
padding-left: 30rpx;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.talk-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-message {
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
color: #888787;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.talk-tag {
|
||||||
|
margin-left: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.talk-time {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.iconBox {
|
||||||
|
width: 94%;
|
||||||
|
margin: 0 3%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
box-shadow: 0 4rpx 24rpx 0 rgba($color: #f6f6f6, $alpha: 1);
|
||||||
|
// transform: translateY(-30rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-list {
|
||||||
|
height: 140rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: $font-sm;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 3%;
|
||||||
|
color: #999;
|
||||||
|
|
||||||
|
.icon-item {
|
||||||
|
position: relative;
|
||||||
|
line-height: 2em;
|
||||||
|
width: 96rpx;
|
||||||
|
|
||||||
|
:first-child {
|
||||||
|
font-size: 48rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bag {
|
||||||
|
width: 56rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bag1 {
|
||||||
|
background: #ff0015;
|
||||||
|
}
|
||||||
|
.bag2 {
|
||||||
|
background: #73AF7C;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "./index-app.scss";
|
||||||
|
</style>
|
|
@ -814,3 +814,4 @@ page,
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -704,7 +704,7 @@ export default {
|
||||||
// lili 基础客服
|
// lili 基础客服
|
||||||
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/tabbar/home/web-view?IM=${this.storeDetail.storeId}`,
|
url: `/pages/mine/im/index?userId=`+this.goodsDetail.storeId,
|
||||||
});
|
});
|
||||||
|
|
||||||
// udesk 代码
|
// udesk 代码
|
||||||
|
|
|
@ -314,17 +314,21 @@ export default {
|
||||||
};
|
};
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url:
|
url:
|
||||||
"/pages/product/customerservice/index?params=" +
|
"/pages/mine/im/index"
|
||||||
encodeURIComponent(JSON.stringify(params)),
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
const sign = this.storeInfo.yzfSign;
|
|
||||||
uni.navigateTo({
|
|
||||||
url:
|
|
||||||
"/pages/tabbar/home/web-view?src=https://yzf.qq.com/xv/web/static/chat/index.html?sign=" +
|
|
||||||
sign,
|
|
||||||
});
|
});
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url:
|
||||||
|
// "/pages/product/customerservice/index?params=" +
|
||||||
|
// encodeURIComponent(JSON.stringify(params)),
|
||||||
|
// });
|
||||||
|
// // #endif
|
||||||
|
// // #ifndef MP-WEIXIN
|
||||||
|
// const sign = this.storeInfo.yzfSign;
|
||||||
|
// uni.navigateTo({
|
||||||
|
// url:
|
||||||
|
// "/pages/tabbar/home/web-view?src=https://yzf.qq.com/xv/web/static/chat/index.html?sign=" +
|
||||||
|
// sign,
|
||||||
|
// });
|
||||||
// #endif
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
</u-row>
|
</u-row>
|
||||||
<!-- 我的订单,代付款 -->
|
<!-- 我的订单,代付款 -->
|
||||||
<view class="order">
|
<view class="order">
|
||||||
|
|
||||||
<view class="order-item" @click="navigateTo('/pages/order/myOrder?status=1')">
|
<view class="order-item" @click="navigateTo('/pages/order/myOrder?status=1')">
|
||||||
<div class="bag bag2">
|
<div class="bag bag2">
|
||||||
<u-icon name="bag-fill" size="35" color="#fff"></u-icon>
|
<u-icon name="bag-fill" size="35" color="#fff"></u-icon>
|
||||||
|
@ -154,6 +153,7 @@ html,
|
||||||
body {
|
body {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.money {
|
.money {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
|
@ -175,12 +175,14 @@ body {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.head-1 {
|
.head-1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 152rpx;
|
width: 152rpx;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
image {
|
image {
|
||||||
width: 152rpx;
|
width: 152rpx;
|
||||||
height: 144rpx;
|
height: 144rpx;
|
||||||
|
@ -188,6 +190,7 @@ body {
|
||||||
margin-bottom: 30rpx;
|
margin-bottom: 30rpx;
|
||||||
border: 3px solid #fff;
|
border: 3px solid #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edti-head {
|
.edti-head {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 40rpx;
|
width: 40rpx;
|
||||||
|
@ -196,23 +199,27 @@ body {
|
||||||
background-color: rgba(255, 255, 255, 0.3);
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
top: 100rpx;
|
top: 100rpx;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
||||||
image {
|
image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.head-2 {
|
.head-2 {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
margin-left: 30rpx;
|
margin-left: 30rpx;
|
||||||
margin-top: 100rpx;
|
margin-top: 100rpx;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/deep/ .u-icon,
|
/deep/ .u-icon,
|
||||||
.u-icon {
|
.u-icon {
|
||||||
margin-top: 106rpx;
|
margin-top: 106rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pointBox {
|
.pointBox {
|
||||||
width: 94%;
|
width: 94%;
|
||||||
margin: 0 3%;
|
margin: 0 3%;
|
||||||
|
@ -220,6 +227,7 @@ body {
|
||||||
border-radius: 20rpx;
|
border-radius: 20rpx;
|
||||||
box-shadow: 0 4rpx 24rpx 0 rgba($color: #f6f6f6, $alpha: 1);
|
box-shadow: 0 4rpx 24rpx 0 rgba($color: #f6f6f6, $alpha: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.point {
|
.point {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 160rpx;
|
height: 160rpx;
|
||||||
|
@ -227,12 +235,14 @@ body {
|
||||||
font-size: $font-sm;
|
font-size: $font-sm;
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
|
|
||||||
// #endif
|
// #endif
|
||||||
.u-col {
|
.u-col {
|
||||||
view {
|
view {
|
||||||
color: $u-main-color;
|
color: $u-main-color;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
view:last-child {
|
view:last-child {
|
||||||
margin-top: 8rpx;
|
margin-top: 8rpx;
|
||||||
color: $main-color;
|
color: $main-color;
|
||||||
|
@ -240,6 +250,7 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.order {
|
.order {
|
||||||
height: 140rpx;
|
height: 140rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -249,10 +260,12 @@ body {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 3%;
|
padding: 0 3%;
|
||||||
color: #999;
|
color: #999;
|
||||||
|
|
||||||
.order-item {
|
.order-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
width: 96rpx;
|
width: 96rpx;
|
||||||
|
|
||||||
:first-child {
|
:first-child {
|
||||||
font-size: 48rpx;
|
font-size: 48rpx;
|
||||||
margin-bottom: 10rpx;
|
margin-bottom: 10rpx;
|
||||||
|
@ -264,6 +277,7 @@ body {
|
||||||
.box {
|
.box {
|
||||||
transform: translateY(-30rpx);
|
transform: translateY(-30rpx);
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-name {
|
.user-name {
|
||||||
font-size: 34rpx;
|
font-size: 34rpx;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ export default {
|
||||||
|
|
||||||
linkMsgDetail(){
|
linkMsgDetail(){
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/tabbar/home/web-view?IM=0`,
|
url: `/pages/mine/im/list`,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
161
utils/filters.js
161
utils/filters.js
|
@ -85,6 +85,62 @@ export function unixToDate(unix, format) {
|
||||||
return _format;
|
return _format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人性化显示时间
|
||||||
|
*
|
||||||
|
* @param {Object} datetime
|
||||||
|
*/
|
||||||
|
export function beautifyTime(datetime = "") {
|
||||||
|
if (datetime == null || datetime == undefined || !datetime) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime = datetime.replace(/-/g, "/");
|
||||||
|
|
||||||
|
let time = new Date();
|
||||||
|
let outTime = new Date(datetime);
|
||||||
|
if (/^[1-9]\d*$/.test(datetime)) {
|
||||||
|
outTime = new Date(parseInt(datetime) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getTime() < outTime.getTime()) {
|
||||||
|
return parseTime(outTime, "{y}/{m}/{d}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getFullYear() != outTime.getFullYear()) {
|
||||||
|
return parseTime(outTime, "{y}/{m}/{d}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getMonth() != outTime.getMonth()) {
|
||||||
|
return parseTime(outTime, "{m}/{d}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getDate() != outTime.getDate()) {
|
||||||
|
let day = outTime.getDate() - time.getDate();
|
||||||
|
if (day == -1) {
|
||||||
|
return parseTime(outTime, "昨天 {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day == -2) {
|
||||||
|
return parseTime(outTime, "前天 {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseTime(outTime, "{m}-{d}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getHours() != outTime.getHours()) {
|
||||||
|
return parseTime(outTime, "{h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let minutes = outTime.getMinutes() - time.getMinutes();
|
||||||
|
if (minutes == 0) {
|
||||||
|
return "刚刚";
|
||||||
|
}
|
||||||
|
|
||||||
|
minutes = Math.abs(minutes);
|
||||||
|
return `${minutes}分钟前`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 13888888888 -> 138****8888
|
* 13888888888 -> 138****8888
|
||||||
* @param mobile
|
* @param mobile
|
||||||
|
@ -98,6 +154,111 @@ export function secrecyMobile(mobile) {
|
||||||
return mobile.replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3");
|
return mobile.replace(/(\d{3})(\d{4})(\d{4})/, "$1****$3");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 人性化时间显示
|
||||||
|
*
|
||||||
|
* @param {Object} datetime
|
||||||
|
*/
|
||||||
|
export function formatTime(datetime) {
|
||||||
|
if (datetime == null) return "";
|
||||||
|
|
||||||
|
datetime = datetime.replace(/-/g, "/");
|
||||||
|
|
||||||
|
let time = new Date();
|
||||||
|
let outTime = new Date(datetime);
|
||||||
|
if (/^[1-9]\d*$/.test(datetime)) {
|
||||||
|
outTime = new Date(parseInt(datetime) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
time.getTime() < outTime.getTime() ||
|
||||||
|
time.getFullYear() != outTime.getFullYear()
|
||||||
|
) {
|
||||||
|
return parseTime(outTime, "{y}-{m}-{d} {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getMonth() != outTime.getMonth()) {
|
||||||
|
return parseTime(outTime, "{m}-{d} {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getDate() != outTime.getDate()) {
|
||||||
|
let day = outTime.getDate() - time.getDate();
|
||||||
|
if (day == -1) {
|
||||||
|
return parseTime(outTime, "昨天 {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day == -2) {
|
||||||
|
return parseTime(outTime, "前天 {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseTime(outTime, "{m}-{d} {h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time.getHours() != outTime.getHours()) {
|
||||||
|
return parseTime(outTime, "{h}:{i}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let minutes = outTime.getMinutes() - time.getMinutes();
|
||||||
|
if (minutes == 0) {
|
||||||
|
return "刚刚";
|
||||||
|
}
|
||||||
|
|
||||||
|
minutes = Math.abs(minutes);
|
||||||
|
return `${minutes}分钟前`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间格式化方法
|
||||||
|
*
|
||||||
|
* @param {(Object|string|number)} time
|
||||||
|
* @param {String} cFormat
|
||||||
|
* @returns {String | null}
|
||||||
|
*/
|
||||||
|
export function parseTime(time, cFormat) {
|
||||||
|
if (arguments.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let date;
|
||||||
|
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
|
||||||
|
|
||||||
|
if (typeof time === "object") {
|
||||||
|
date = time;
|
||||||
|
} else {
|
||||||
|
if (typeof time === "string" && /^[0-9]+$/.test(time)) {
|
||||||
|
time = parseInt(time);
|
||||||
|
}
|
||||||
|
if (typeof time === "number" && time.toString().length === 10) {
|
||||||
|
time = time * 1000;
|
||||||
|
console.log("时间判断为number");
|
||||||
|
}
|
||||||
|
|
||||||
|
date = new Date(time.replace(/-/g, "/"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatObj = {
|
||||||
|
y: date.getFullYear(),
|
||||||
|
m: date.getMonth() + 1,
|
||||||
|
d: date.getDate(),
|
||||||
|
h: date.getHours(),
|
||||||
|
i: date.getMinutes(),
|
||||||
|
s: date.getSeconds(),
|
||||||
|
a: date.getDay(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
|
||||||
|
const value = formatObj[key];
|
||||||
|
// Note: getDay() returns 0 on Sunday
|
||||||
|
if (key === "a") {
|
||||||
|
return ["日", "一", "二", "三", "四", "五", "六"][value];
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.toString().padStart(2, "0");
|
||||||
|
});
|
||||||
|
|
||||||
|
return time_str;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除逗号
|
* 清除逗号
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
import store from '@/store/index'
|
||||||
|
import config from '@/config/config.js'
|
||||||
|
import storage from './storage';
|
||||||
|
export default class SocketService {
|
||||||
|
/**
|
||||||
|
* 单例
|
||||||
|
*/
|
||||||
|
static instance = null;
|
||||||
|
static get Instance() {
|
||||||
|
if (!this.instance) {
|
||||||
|
this.instance = new SocketService();
|
||||||
|
}
|
||||||
|
return this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 和服务端连接的socket对象
|
||||||
|
ws = null;
|
||||||
|
|
||||||
|
// 存储回调函数
|
||||||
|
callBackMapping = {};
|
||||||
|
|
||||||
|
// 标识是否连接成功
|
||||||
|
connected = false;
|
||||||
|
|
||||||
|
// 记录重试的次数
|
||||||
|
sendRetryCount = 0;
|
||||||
|
|
||||||
|
// 重新连接尝试的次数
|
||||||
|
connectRetryCount = 0;
|
||||||
|
|
||||||
|
// 定义连接服务器的方法
|
||||||
|
connect() {
|
||||||
|
// 连接服务器
|
||||||
|
if (!window.WebSocket) {
|
||||||
|
return console.log("您的浏览器不支持WebSocket");
|
||||||
|
}
|
||||||
|
this.ws = new WebSocket(config.BASE_WS_URL+'/'+storage.getAccessToken());
|
||||||
|
// 连接成功的事件
|
||||||
|
this.ws.onopen = () => {
|
||||||
|
console.log("连接服务端成功");
|
||||||
|
this.connected = true;
|
||||||
|
// 重置重新连接的次数
|
||||||
|
this.connectRetryCount = 0;
|
||||||
|
};
|
||||||
|
// 1.连接服务端失败
|
||||||
|
// 2.当连接成功之后, 服务器关闭的情况(连接失败重连)
|
||||||
|
this.ws.onclose = () => {
|
||||||
|
console.log("连接服务端失败");
|
||||||
|
this.connected = false;
|
||||||
|
this.connectRetryCount++;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.connect();
|
||||||
|
}, 500 * this.connectRetryCount);
|
||||||
|
};
|
||||||
|
// 得到服务端发送过来的数据
|
||||||
|
this.ws.onmessage = (msg) => {
|
||||||
|
// console.log(msg.data)
|
||||||
|
this.registerCallBack(msg.data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 回调函数的注册
|
||||||
|
registerCallBack(callBack) {
|
||||||
|
// console.log("回调函数的注册", callBack);
|
||||||
|
this.callBackMapping = callBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取消某一个回调函数
|
||||||
|
unRegisterCallBack(callBack) {
|
||||||
|
console.log("取消某一个回调函数", callBack);
|
||||||
|
this.callBackMapping = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送数据的方法
|
||||||
|
send(data) {
|
||||||
|
// 判断此时此刻有没有连接成功
|
||||||
|
if (this.connected) {
|
||||||
|
this.sendRetryCount = 0;
|
||||||
|
this.ws.send(data);
|
||||||
|
} else {
|
||||||
|
this.sendRetryCount++;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.send(data);
|
||||||
|
}, this.sendRetryCount * 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,12 @@ export default {
|
||||||
getUserInfo() {
|
getUserInfo() {
|
||||||
return uni.getStorageSync(USER_INFO);
|
return uni.getStorageSync(USER_INFO);
|
||||||
},
|
},
|
||||||
|
setTalkToUser(val){
|
||||||
|
uni.setStorageSync("TALK_TO_USER", val);
|
||||||
|
},
|
||||||
|
getTalkToUser(){
|
||||||
|
return uni.getStorageSync("TALK_TO_USER");
|
||||||
|
},
|
||||||
// 写入uuid
|
// 写入uuid
|
||||||
setUuid(val) {
|
setUuid(val) {
|
||||||
uni.setStorageSync(UUID, val);
|
uni.setStorageSync(UUID, val);
|
||||||
|
|
Loading…
Reference in New Issue