19 changed files with 1143 additions and 1209 deletions
-
4App.vue
-
44pages/home/user.vue
-
18pages/setting/setting.vue
-
11pages/user/login.vue
-
5store/modules/user.js
-
6uni_modules/vrapile-im/components/vrapile-im/vrapile-im.vue
-
660uni_modules/vrapile-im/pages/chat/chatFriend.vue
-
352uni_modules/vrapile-im/pages/home/chatHome.vue
-
36uni_modules/vrapile-im/pages_init.json
-
52uni_modules/vrapile-im/readme.md
-
220uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss
-
148uni_modules/vrapile-im/static/style/nine-chat-home-001.scss
-
2uni_modules/vrapile-im/store/getters.js
-
287uni_modules/vrapile-im/store/modules/chat.js
-
216uni_modules/vrapile-im/store/modules/socket.js
-
154uni_modules/vrapile-im/utils/nineTool.js
-
2uni_modules/vrapile-im/utils/storage.js
-
134uni_modules/vrapile-im/utils/tiosocket.js
-
1utils/request.js
@ -1,5 +1,5 @@ |
|||
<template> |
|||
<view> |
|||
vrapile-im页面组件,此文件不会被引用 |
|||
</view> |
|||
<view> |
|||
vrapile-im页面组件,此文件不会被引用 |
|||
</view> |
|||
</template> |
|||
@ -1,337 +1,337 @@ |
|||
<template> |
|||
<view class="nine-content-001"> |
|||
<view class="chat-body"> |
|||
<view class="chat-body-main"> |
|||
<view v-if="chatObject.haveHistory==0" class="chat-body-history"> |
|||
没有更多消息了 |
|||
</view> |
|||
<view v-else class="chat-body-history chat-body-history-have" @click="handleHistoryMessage(false)"> |
|||
查看更多消息 |
|||
</view> |
|||
<view class="chat-body-message"> |
|||
<view v-for="(item, index) in messageList" :key="index"> |
|||
<view class="chat-conversation" :class="item.fromId == userInfo.userId?'chat-conversation-mine':''"> |
|||
<view class="chat-conversation-image"> |
|||
<image class="chat-conversation-image-image" v-if="item.fromId != userInfo.userId" :src="getUserAvatar(item.fromId, item.avatar)"></image> |
|||
<image class="chat-conversation-image-image" v-else :src="userInfo.avatar || defaultAvatar"></image> |
|||
</view> |
|||
<view class="chat-conversation-text"> |
|||
<view class="chat-conversation-text-time" v-if="item.sendType == 1 && item.fromId != userInfo.userId">{{getUserName(item.fromId, item.fromName)}}</view> |
|||
<view class="chat-conversation-text-time">{{formatTime(item.sendTime)}}</view> |
|||
<view class="chat-conversation-text-text nine-user-select">{{item.content}}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="chat-footer"> |
|||
<view class="chat-footer-send"> |
|||
<view @click="handleVoice" class="chat-footer-send-voice"> |
|||
<image class="chat-footer-send-image" :src="iconVoice"></image> |
|||
</view> |
|||
<view v-if="isVoice" @longpress="handleSay" class="chat-footer-send-say"> |
|||
<span>按住 说话</span> |
|||
</view> |
|||
<view v-else class="chat-footer-send-input"> |
|||
<input @confirm="handleSend" class="input" v-model="inputText" /> |
|||
</view> |
|||
<view @click="handleEmoji" class="chat-footer-send-emoji"> |
|||
<image class="chat-footer-send-image" :src="iconEmoji"></image> |
|||
</view> |
|||
<view v-if="inputText" @click="handleSend" class="chat-footer-send-button"> |
|||
<span class="chat-footer-send-button-span">发送</span> |
|||
</view> |
|||
<view v-else @click="handleMore" class="chat-footer-send-more"> |
|||
<image class="chat-footer-send-image" :src="iconMore"></image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="nine-content-001"> |
|||
<view class="chat-body"> |
|||
<view class="chat-body-main"> |
|||
<view v-if="chatObject.haveHistory==0" class="chat-body-history"> |
|||
没有更多消息了 |
|||
</view> |
|||
<view v-else class="chat-body-history chat-body-history-have" @click="handleHistoryMessage(false)"> |
|||
查看更多消息 |
|||
</view> |
|||
<view class="chat-body-message"> |
|||
<view v-for="(item, index) in messageList" :key="index"> |
|||
<view class="chat-conversation" :class="item.fromId == userInfo.userId?'chat-conversation-mine':''"> |
|||
<view class="chat-conversation-image"> |
|||
<image class="chat-conversation-image-image" v-if="item.fromId != userInfo.userId" :src="getUserAvatar(item.fromId, item.avatar)"></image> |
|||
<image class="chat-conversation-image-image" v-else :src="userInfo.avatar || defaultAvatar"></image> |
|||
</view> |
|||
<view class="chat-conversation-text"> |
|||
<view class="chat-conversation-text-time" v-if="item.sendType == 1 && item.fromId != userInfo.userId">{{getUserName(item.fromId, item.fromName)}}</view> |
|||
<view class="chat-conversation-text-time">{{formatTime(item.sendTime)}}</view> |
|||
<view class="chat-conversation-text-text nine-user-select">{{item.content}}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="chat-footer"> |
|||
<view class="chat-footer-send"> |
|||
<view @click="handleVoice" class="chat-footer-send-voice"> |
|||
<image class="chat-footer-send-image" :src="iconVoice"></image> |
|||
</view> |
|||
<view v-if="isVoice" @longpress="handleSay" class="chat-footer-send-say"> |
|||
<span>按住 说话</span> |
|||
</view> |
|||
<view v-else class="chat-footer-send-input"> |
|||
<input @confirm="handleSend" class="input" v-model="inputText" /> |
|||
</view> |
|||
<view @click="handleEmoji" class="chat-footer-send-emoji"> |
|||
<image class="chat-footer-send-image" :src="iconEmoji"></image> |
|||
</view> |
|||
<view v-if="inputText" @click="handleSend" class="chat-footer-send-button"> |
|||
<span class="chat-footer-send-button-span">发送</span> |
|||
</view> |
|||
<view v-else @click="handleMore" class="chat-footer-send-more"> |
|||
<image class="chat-footer-send-image" :src="iconMore"></image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState } from 'vuex' |
|||
import store from '@/uni_modules/vrapile-im/store' |
|||
import { getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; |
|||
// 外部需提供store用于获取用户信息,提供根据消息key查询用户历史消息接口 |
|||
import storeOut from '@/store' |
|||
import { getMessageByChatKey } from '@/api/chat' |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {}, |
|||
|
|||
chatObject: {}, |
|||
messageList: [], |
|||
noHistory: true, |
|||
isVoice: false, |
|||
inputText: "", |
|||
|
|||
// 消息唯一key |
|||
key: null, |
|||
|
|||
// 用户默认图标 |
|||
defaultAvatar: '/uni_modules/vrapile-im/static/image/yy.png', |
|||
// 消息铃铛图标 |
|||
iconMessage: "/uni_modules/vrapile-im/static/image/message.png", |
|||
// 语音切换图标 |
|||
iconVoice: "/uni_modules/vrapile-im/static/image/voice.png", |
|||
// 表情图标 |
|||
iconEmoji: "/uni_modules/vrapile-im/static/image/emoji.png", |
|||
// 更多图标 |
|||
iconMore: "/uni_modules/vrapile-im/static/image/more.png", |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapState({ |
|||
websocketData: state => store.state.socket.websocketData |
|||
}), |
|||
getChatList() { |
|||
return store.state.chat.chatList; |
|||
}, |
|||
getUserAvatar() { |
|||
return (userId, defaultAvatar) => { |
|||
return store.getters.getUserAvatar(userId, defaultAvatar); |
|||
} |
|||
}, |
|||
getUserName() { |
|||
return (userId, defaultName) => { |
|||
return store.getters.getUserName(userId, defaultName); |
|||
} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.userInfo = storeOut.state.user.userInfo; |
|||
if(!this.userInfo.userId){ |
|||
this.navigateToLogin(); |
|||
} |
|||
try{ |
|||
this.key = options.data; |
|||
}catch(e){ |
|||
this.switchTab("/uni_modules/vrapile-im/pages/home/chatHome"); |
|||
} |
|||
}, |
|||
// 下拉处理 |
|||
onPullDownRefresh() { |
|||
if(this.chatObject.haveHistory==1){ |
|||
this.handleHistoryMessage(true); |
|||
} |
|||
setTimeout(() => { |
|||
uni.stopPullDownRefresh(); |
|||
}, 500); |
|||
}, |
|||
onShow(){ |
|||
for(let i=0; i < this.getChatList.length; i++){ |
|||
if(this.getChatList[i]["key"] == this.key){ |
|||
this.chatObject = this.getChatList[i]; |
|||
uni.setNavigationBarTitle({ |
|||
title: this.chatObject.name || "好友" |
|||
}) |
|||
this.messageList = this.getChatList[i].messageList; |
|||
this.scrollToBottom(); |
|||
if(this.messageList.length == 0 && this.chatObject.haveHistory==1){ |
|||
this.handleHistoryMessage(true); |
|||
}else{ |
|||
this.handleRead(); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
}, |
|||
// 监听消息 |
|||
watch: { |
|||
websocketData: { |
|||
handler(newVal, oldval) { |
|||
if(newVal && newVal.length > 0 |
|||
&& (newVal[newVal.length-1]["toId"] == this.userInfo.userId |
|||
|| newVal[newVal.length-1]["fromId"] == this.userInfo.userId)){ |
|||
this.scrollToBottom(); |
|||
this.handleRead(); |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
// 滚动到最新消息位置 |
|||
scrollToBottom() { |
|||
setTimeout(() => { |
|||
uni.pageScrollTo({ |
|||
scrollTop: 2000000, |
|||
duration : 10 |
|||
}) |
|||
}, 500); |
|||
}, |
|||
// 语音点击事件 |
|||
handleVoice() { |
|||
this.isVoice = !this.isVoice; |
|||
}, |
|||
// 语音消息处理, 暂时先发送个提示 |
|||
handleSay() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一条语音消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 表情消息处理, 暂时先发送个提示 |
|||
handleEmoji() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一个表情消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 更多消息处理, 暂时先发送个提示 |
|||
handleMore() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一个更多的消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 反馈已读 |
|||
handleRead() { |
|||
let sendInfo = { |
|||
code: 3, |
|||
message: { |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
userId: this.userInfo.userId, |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
store.commit('READ_MESSAGE', this.key); |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, |
|||
// 发送消息 |
|||
handleSend() { |
|||
if(!this.inputText){ |
|||
return; |
|||
} |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: this.inputText, |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展内容 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
this.inputText = ""; |
|||
}, |
|||
// 获取历史消息 |
|||
handleHistoryMessage(scrollFlag=false){ |
|||
let limit = this.chatObject["messageList"].length + 10; |
|||
getMessageByChatKey({ |
|||
type: this.chatObject.type, |
|||
key: this.chatObject["key"], |
|||
groupId: this.chatObject.id, |
|||
limit: limit |
|||
}).then(res => { |
|||
if(res.data.length > 0){ |
|||
this.messageList = res.data; |
|||
this.chatObject["messageList"] = this.messageList; |
|||
let lastMessage = res.data[res.data.length-1]; |
|||
this.chatObject["messageLast"] = lastMessage; |
|||
if(lastMessage["sendType"] == 0){ |
|||
this.chatObject["messageShow"] = lastMessage["content"]; |
|||
}else{ |
|||
this.chatObject["messageShow"] = store.getters.getUserName(lastMessage["fromId"], lastMessage["fromName"]) + ": " + lastMessage["content"] |
|||
} |
|||
this.chatObject["messageTime"] = this.formatDate(lastMessage["sendTime"]); |
|||
} |
|||
if(res.data.length < limit){ |
|||
this.chatObject["haveHistory"] = 0; |
|||
} |
|||
|
|||
for(let i=0; i < this.getChatList.length; i++){ |
|||
if(this.getChatList[i]["key"] == this.key){ |
|||
this.$set(this.getChatList, i, this.chatObject) |
|||
break; |
|||
} |
|||
} |
|||
if(scrollFlag){ |
|||
this.scrollToBottom(); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
import { mapState } from 'vuex' |
|||
import store from '@/uni_modules/vrapile-im/store' |
|||
import { getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; |
|||
// 外部需提供store用于获取用户信息,提供根据消息key查询用户历史消息接口 |
|||
import storeOut from '@/store' |
|||
import { getMessageByChatKey } from '@/api/chat' |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {}, |
|||
|
|||
chatObject: {}, |
|||
messageList: [], |
|||
noHistory: true, |
|||
isVoice: false, |
|||
inputText: "", |
|||
|
|||
// 消息唯一key |
|||
key: null, |
|||
|
|||
// 用户默认图标 |
|||
defaultAvatar: '/uni_modules/vrapile-im/static/image/yy.png', |
|||
// 消息铃铛图标 |
|||
iconMessage: "/uni_modules/vrapile-im/static/image/message.png", |
|||
// 语音切换图标 |
|||
iconVoice: "/uni_modules/vrapile-im/static/image/voice.png", |
|||
// 表情图标 |
|||
iconEmoji: "/uni_modules/vrapile-im/static/image/emoji.png", |
|||
// 更多图标 |
|||
iconMore: "/uni_modules/vrapile-im/static/image/more.png", |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapState({ |
|||
websocketData: state => store.state.socket.websocketData |
|||
}), |
|||
getChatList() { |
|||
return store.state.chat.chatList; |
|||
}, |
|||
getUserAvatar() { |
|||
return (userId, defaultAvatar) => { |
|||
return store.getters.getUserAvatar(userId, defaultAvatar); |
|||
} |
|||
}, |
|||
getUserName() { |
|||
return (userId, defaultName) => { |
|||
return store.getters.getUserName(userId, defaultName); |
|||
} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.userInfo = storeOut.state.user.userInfo; |
|||
if(!this.userInfo.userId){ |
|||
this.navigateToLogin(); |
|||
} |
|||
try{ |
|||
this.key = options.data; |
|||
}catch(e){ |
|||
this.switchTab("/uni_modules/vrapile-im/pages/home/chatHome"); |
|||
} |
|||
}, |
|||
// 下拉处理 |
|||
onPullDownRefresh() { |
|||
if(this.chatObject.haveHistory==1){ |
|||
this.handleHistoryMessage(true); |
|||
} |
|||
setTimeout(() => { |
|||
uni.stopPullDownRefresh(); |
|||
}, 500); |
|||
}, |
|||
onShow(){ |
|||
for(let i=0; i < this.getChatList.length; i++){ |
|||
if(this.getChatList[i]["key"] == this.key){ |
|||
this.chatObject = this.getChatList[i]; |
|||
uni.setNavigationBarTitle({ |
|||
title: this.chatObject.name || "好友" |
|||
}) |
|||
this.messageList = this.getChatList[i].messageList; |
|||
this.scrollToBottom(); |
|||
if(this.messageList.length == 0 && this.chatObject.haveHistory==1){ |
|||
this.handleHistoryMessage(true); |
|||
}else{ |
|||
this.handleRead(); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
}, |
|||
// 监听消息 |
|||
watch: { |
|||
websocketData: { |
|||
handler(newVal, oldval) { |
|||
if(newVal && newVal.length > 0 |
|||
&& (newVal[newVal.length-1]["toId"] == this.userInfo.userId |
|||
|| newVal[newVal.length-1]["fromId"] == this.userInfo.userId)){ |
|||
this.scrollToBottom(); |
|||
this.handleRead(); |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
// 滚动到最新消息位置 |
|||
scrollToBottom() { |
|||
setTimeout(() => { |
|||
uni.pageScrollTo({ |
|||
scrollTop: 2000000, |
|||
duration : 10 |
|||
}) |
|||
}, 500); |
|||
}, |
|||
// 语音点击事件 |
|||
handleVoice() { |
|||
this.isVoice = !this.isVoice; |
|||
}, |
|||
// 语音消息处理, 暂时先发送个提示 |
|||
handleSay() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一条语音消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 表情消息处理, 暂时先发送个提示 |
|||
handleEmoji() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一个表情消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 更多消息处理, 暂时先发送个提示 |
|||
handleMore() { |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: "您发送了一个更多的消息", |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展消息 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
}, |
|||
// 反馈已读 |
|||
handleRead() { |
|||
let sendInfo = { |
|||
code: 3, |
|||
message: { |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
userId: this.userInfo.userId, |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
store.commit('READ_MESSAGE', this.key); |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, |
|||
// 发送消息 |
|||
handleSend() { |
|||
if(!this.inputText){ |
|||
return; |
|||
} |
|||
let sendInfo = { |
|||
code: 2, |
|||
message: { |
|||
//消息文件类型 0-文本|1-图片|2-附件|3-语言|4-撤回 |
|||
messageType: 0, |
|||
//聊天室id |
|||
toId: this.chatObject.id, |
|||
//消息发送人 |
|||
fromId: this.userInfo.userId, |
|||
//消息发送人账号 |
|||
fromName: this.userInfo.userName, |
|||
//消息内容 |
|||
content: this.inputText, |
|||
//消息类型:0-私聊|1-群聊 |
|||
sendType: this.chatObject.type, |
|||
//扩展内容 |
|||
extend: null |
|||
}, |
|||
}; |
|||
uni.sendSocketMessage({ |
|||
data: JSON.stringify(sendInfo) |
|||
}) |
|||
this.inputText = ""; |
|||
}, |
|||
// 获取历史消息 |
|||
handleHistoryMessage(scrollFlag=false){ |
|||
let limit = this.chatObject["messageList"].length + 10; |
|||
getMessageByChatKey({ |
|||
type: this.chatObject.type, |
|||
key: this.chatObject["key"], |
|||
groupId: this.chatObject.id, |
|||
limit: limit |
|||
}).then(res => { |
|||
if(res.data.length > 0){ |
|||
this.messageList = res.data; |
|||
this.chatObject["messageList"] = this.messageList; |
|||
let lastMessage = res.data[res.data.length-1]; |
|||
this.chatObject["messageLast"] = lastMessage; |
|||
if(lastMessage["sendType"] == 0){ |
|||
this.chatObject["messageShow"] = lastMessage["content"]; |
|||
}else{ |
|||
this.chatObject["messageShow"] = store.getters.getUserName(lastMessage["fromId"], lastMessage["fromName"]) + ": " + lastMessage["content"] |
|||
} |
|||
this.chatObject["messageTime"] = this.formatDate(lastMessage["sendTime"]); |
|||
} |
|||
if(res.data.length < limit){ |
|||
this.chatObject["haveHistory"] = 0; |
|||
} |
|||
|
|||
for(let i=0; i < this.getChatList.length; i++){ |
|||
if(this.getChatList[i]["key"] == this.key){ |
|||
this.$set(this.getChatList, i, this.chatObject) |
|||
break; |
|||
} |
|||
} |
|||
if(scrollFlag){ |
|||
this.scrollToBottom(); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
/* 重写外部nine-chat-friend-001.scss可实现样式改变 */ |
|||
@import '/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss'; |
|||
@import '/static/style/nine-chat-friend-001.scss'; |
|||
/* 重写外部nine-chat-friend-001.scss可实现样式改变 */ |
|||
@import '/uni_modules/vrapile-im/static/style/nine-chat-friend-001.scss'; |
|||
@import '/static/style/nine-chat-friend-001.scss'; |
|||
</style> |
|||
@ -1,184 +1,184 @@ |
|||
<template> |
|||
<view class="nine-content-002"> |
|||
<view class="chat-search"> |
|||
<input class="chat-search-input" v-model="searchVal"/> |
|||
<uni-icons class="chat-search-image" type="search" size="24"></uni-icons> |
|||
</view> |
|||
<view class="chat-list"> |
|||
<view class="chat-list-item" v-for="(item,index) in getChatFilterList" :key="index" @click="goToChat(item.key)"> |
|||
<view class="chat-list-item-left"> |
|||
<image class="chat-list-item-left-image" mode="scaleToFill" v-if="item.fromId != userInfo.userId" :src="getUserAvatar(item.fromId, item.avatar)"></image> |
|||
<image class="chat-list-item-left-image" mode="scaleToFill" v-else :src="userInfo.avatar || defaultAvatar"></image> |
|||
<view v-if="item.messageNum > 0" class="chat-list-item-left-mark"> |
|||
{{ item.messageNum < 100 ? item.messageNum : 99 }} |
|||
</view> |
|||
</view> |
|||
<view class="chat-list-item-center"> |
|||
<view class="chat-list-item-center-top"> |
|||
{{ item.name }} |
|||
</view> |
|||
<view class="chat-list-item-center-bottom"> |
|||
{{ item.messageShow || " " }} |
|||
</view> |
|||
</view> |
|||
<view class="chat-list-item-right"> |
|||
<view class="chat-list-item-right-top"> |
|||
{{ item.messageTime || '\xa0' }} |
|||
</view> |
|||
<view class="chat-list-item-right-bottom"> |
|||
<image class="chat-list-item-right-bottom-image" mode="scaleToFill" :src="iconMessage"> |
|||
</image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="nine-content-002"> |
|||
<view class="chat-search"> |
|||
<input class="chat-search-input" v-model="searchVal"/> |
|||
<uni-icons class="chat-search-image" type="search" size="24"></uni-icons> |
|||
</view> |
|||
<view class="chat-list"> |
|||
<view class="chat-list-item" v-for="(item,index) in getChatFilterList" :key="index" @click="goToChat(item.key)"> |
|||
<view class="chat-list-item-left"> |
|||
<image class="chat-list-item-left-image" mode="scaleToFill" v-if="item.fromId != userInfo.userId" :src="getUserAvatar(item.fromId, item.avatar)"></image> |
|||
<image class="chat-list-item-left-image" mode="scaleToFill" v-else :src="userInfo.avatar || defaultAvatar"></image> |
|||
<view v-if="item.messageNum > 0" class="chat-list-item-left-mark"> |
|||
{{ item.messageNum < 100 ? item.messageNum : 99 }} |
|||
</view> |
|||
</view> |
|||
<view class="chat-list-item-center"> |
|||
<view class="chat-list-item-center-top"> |
|||
{{ item.name }} |
|||
</view> |
|||
<view class="chat-list-item-center-bottom"> |
|||
{{ item.messageShow || " " }} |
|||
</view> |
|||
</view> |
|||
<view class="chat-list-item-right"> |
|||
<view class="chat-list-item-right-top"> |
|||
{{ item.messageTime || '\xa0' }} |
|||
</view> |
|||
<view class="chat-list-item-right-bottom"> |
|||
<image class="chat-list-item-right-bottom-image" mode="scaleToFill" :src="iconMessage"> |
|||
</image> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { mapState } from 'vuex' |
|||
import store from '@/uni_modules/vrapile-im/store' |
|||
import { getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; |
|||
// 外部需提供store用于获取用户信息,提供websocket接口地址,提供获取token函数并可以获取token,提供根据消息key查询用户历史消息接口 |
|||
import storeOut from '@/store' |
|||
import { mapState } from 'vuex' |
|||
import store from '@/uni_modules/vrapile-im/store' |
|||
import { getChatKey } from '@/uni_modules/vrapile-im/utils/tiosocket'; |
|||
// 外部需提供store用于获取用户信息,提供websocket接口地址,提供获取token函数并可以获取token,提供根据消息key查询用户历史消息接口 |
|||
import storeOut from '@/store' |
|||
import { getToken } from '@/utils/token' |
|||
import { getMessageByChatKey } from '@/api/chat' |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {}, |
|||
|
|||
searchVal: "", |
|||
|
|||
// 用户默认图标 |
|||
defaultAvatar: '/uni_modules/vrapile-im/static/image/yy.png', |
|||
// 消息铃铛图标 |
|||
iconMessage: "/uni_modules/vrapile-im/static/image/message.png" |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapState({ |
|||
websocketData: state => store.state.socket.websocketData |
|||
}), |
|||
getChatList() { |
|||
return store.state.chat.chatList; |
|||
}, |
|||
getChatFilterList() { |
|||
let list = JSON.parse(JSON.stringify(store.state.chat.chatList)) |
|||
list.sort((a, b) => { |
|||
if(a.messageNum > 0 && b.messageNum > 0){ |
|||
return b.messageLast.sendTime - a.messageLast.sendTime |
|||
} |
|||
if(a.messageList.length == 0 || b.messageList.length == 0){ |
|||
return b.messageList.length - a.messageList.length |
|||
} |
|||
if(a.messageNum == 0 && b.messageNum == 0){ |
|||
return b.messageLast.sendTime - a.messageLast.sendTime |
|||
} |
|||
return b.messageNum - a.messageNum |
|||
}) |
|||
if(this.searchVal){ |
|||
return list.filter(item => { |
|||
if(item.name && item.name.includes(this.searchVal) |
|||
|| item.remarkName && item.remarkName.includes(this.searchVal) |
|||
|| item.userName && item.userName.includes(this.searchVal)){ |
|||
return item; |
|||
} |
|||
for(let message of item.messageList){ |
|||
if(message.content && message.content.includes(this.searchVal)){ |
|||
return item; |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
return list; |
|||
}, |
|||
getUserAvatar() { |
|||
return (userId, defaultAvatar) => { |
|||
return store.getters.getUserAvatar(userId, defaultAvatar); |
|||
} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.userInfo = storeOut.state.user.userInfo; |
|||
}, |
|||
onShow(){ |
|||
setTimeout(()=>{ |
|||
this.dealUnReadMessage(); |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, 500) |
|||
setTimeout(()=>{ |
|||
this.noListDo(); |
|||
}, 3000) |
|||
}, |
|||
activated(){ |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, |
|||
// 监听消息 |
|||
watch: { |
|||
websocketData: { |
|||
handler(newVal, oldval) { |
|||
for(let i=0;i<this.getChatList.length;i++){ |
|||
this.$set(this.getChatList, i, this.getChatList[i]) |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
// 处理未读消息 |
|||
dealUnReadMessage() { |
|||
for(let i=0;i<this.getChatList.length;i++){ |
|||
if(this.getChatList[i]["messageList"].length == 0 && this.getChatList[i]["haveHistory"] == 1){ |
|||
this.handleHistoryMessage(i, false); |
|||
} |
|||
} |
|||
}, |
|||
// 无任何数据,重写获取聊天列表和连接socket |
|||
noListDo(){ |
|||
if(storeOut.state.user.userInfo.userId && (!this.getChatList || this.getChatList.length == 0)){ |
|||
store.dispatch('GetChatList', {userId: storeOut.state.user.userInfo.userId}).then(res => { |
|||
store.dispatch('ConnSocket', { url: import.meta.env.VITE_APP_SOCKET_URL, token: getToken() }); |
|||
}); |
|||
} |
|||
}, |
|||
// 获取历史消息 |
|||
handleHistoryMessage(i, scrollFlag){ |
|||
let limit = this.getChatList[i]["messageList"].length + 10; |
|||
getMessageByChatKey({ |
|||
type: this.getChatList[i].type, |
|||
key: this.getChatList[i]["key"], |
|||
groupId: this.getChatList[i].id, |
|||
limit: limit |
|||
}).then(res => { |
|||
if(res.data.length > 0){ |
|||
this.getChatList[i]["messageList"] = res.data; |
|||
let lastMessage = res.data[res.data.length-1]; |
|||
this.getChatList[i]["messageLast"] = lastMessage; |
|||
if(lastMessage["sendType"] == 0){ |
|||
this.getChatList[i]["messageShow"] = lastMessage["content"]; |
|||
}else{ |
|||
this.getChatList[i]["messageShow"] = store.getters.getUserName(lastMessage["fromId"], lastMessage["fromName"]) + ": " + lastMessage["content"] |
|||
} |
|||
this.getChatList[i]["messageTime"] = this.formatDate(lastMessage["sendTime"]); |
|||
} |
|||
if(res.data.length < limit){ |
|||
this.getChatList[i]["haveHistory"] = 0; |
|||
} |
|||
|
|||
this.$set(this.getChatList, i, this.getChatList[i]) |
|||
}); |
|||
}, |
|||
// 跳转到聊天页面 |
|||
goToChat(key) { |
|||
this.navigateTo("/uni_modules/vrapile-im/pages/chat/chatFriend?data=" + key) |
|||
} |
|||
} |
|||
} |
|||
import { getMessageByChatKey } from '@/api/chat' |
|||
export default { |
|||
data() { |
|||
return { |
|||
userInfo: {}, |
|||
|
|||
searchVal: "", |
|||
|
|||
// 用户默认图标 |
|||
defaultAvatar: '/uni_modules/vrapile-im/static/image/yy.png', |
|||
// 消息铃铛图标 |
|||
iconMessage: "/uni_modules/vrapile-im/static/image/message.png" |
|||
} |
|||
}, |
|||
computed: { |
|||
...mapState({ |
|||
websocketData: state => store.state.socket.websocketData |
|||
}), |
|||
getChatList() { |
|||
return store.state.chat.chatList; |
|||
}, |
|||
getChatFilterList() { |
|||
let list = JSON.parse(JSON.stringify(store.state.chat.chatList)) |
|||
list.sort((a, b) => { |
|||
if(a.messageNum > 0 && b.messageNum > 0){ |
|||
return b.messageLast.sendTime - a.messageLast.sendTime |
|||
} |
|||
if(a.messageList.length == 0 || b.messageList.length == 0){ |
|||
return b.messageList.length - a.messageList.length |
|||
} |
|||
if(a.messageNum == 0 && b.messageNum == 0){ |
|||
return b.messageLast.sendTime - a.messageLast.sendTime |
|||
} |
|||
return b.messageNum - a.messageNum |
|||
}) |
|||
if(this.searchVal){ |
|||
return list.filter(item => { |
|||
if(item.name && item.name.includes(this.searchVal) |
|||
|| item.remarkName && item.remarkName.includes(this.searchVal) |
|||
|| item.userName && item.userName.includes(this.searchVal)){ |
|||
return item; |
|||
} |
|||
for(let message of item.messageList){ |
|||
if(message.content && message.content.includes(this.searchVal)){ |
|||
return item; |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
return list; |
|||
}, |
|||
getUserAvatar() { |
|||
return (userId, defaultAvatar) => { |
|||
return store.getters.getUserAvatar(userId, defaultAvatar); |
|||
} |
|||
} |
|||
}, |
|||
onLoad(options){ |
|||
this.userInfo = storeOut.state.user.userInfo; |
|||
}, |
|||
onShow(){ |
|||
setTimeout(()=>{ |
|||
this.dealUnReadMessage(); |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, 500) |
|||
setTimeout(()=>{ |
|||
this.noListDo(); |
|||
}, 3000) |
|||
}, |
|||
activated(){ |
|||
store.commit('COUNT_MESSAGE'); |
|||
}, |
|||
// 监听消息 |
|||
watch: { |
|||
websocketData: { |
|||
handler(newVal, oldval) { |
|||
for(let i=0;i<this.getChatList.length;i++){ |
|||
this.$set(this.getChatList, i, this.getChatList[i]) |
|||
} |
|||
}, |
|||
immediate: true, |
|||
deep: true |
|||
} |
|||
}, |
|||
methods: { |
|||
// 处理未读消息 |
|||
dealUnReadMessage() { |
|||
for(let i=0;i<this.getChatList.length;i++){ |
|||
if(this.getChatList[i]["messageList"].length == 0 && this.getChatList[i]["haveHistory"] == 1){ |
|||
this.handleHistoryMessage(i, false); |
|||
} |
|||
} |
|||
}, |
|||
// 无任何数据,重写获取聊天列表和连接socket |
|||
noListDo(){ |
|||
if(storeOut.state.user.userInfo.userId && (!this.getChatList || this.getChatList.length == 0)){ |
|||
store.dispatch('GetChatList').then(res => { |
|||
store.dispatch('ConnSocket'); |
|||
}); |
|||
} |
|||
}, |
|||
// 获取历史消息 |
|||
handleHistoryMessage(i, scrollFlag){ |
|||
let limit = this.getChatList[i]["messageList"].length + 10; |
|||
getMessageByChatKey({ |
|||
type: this.getChatList[i].type, |
|||
key: this.getChatList[i]["key"], |
|||
groupId: this.getChatList[i].id, |
|||
limit: limit |
|||
}).then(res => { |
|||
if(res.data.length > 0){ |
|||
this.getChatList[i]["messageList"] = res.data; |
|||
let lastMessage = res.data[res.data.length-1]; |
|||
this.getChatList[i]["messageLast"] = lastMessage; |
|||
if(lastMessage["sendType"] == 0){ |
|||
this.getChatList[i]["messageShow"] = lastMessage["content"]; |
|||
}else{ |
|||
this.getChatList[i]["messageShow"] = store.getters.getUserName(lastMessage["fromId"], lastMessage["fromName"]) + ": " + lastMessage["content"] |
|||
} |
|||
this.getChatList[i]["messageTime"] = this.formatDate(lastMessage["sendTime"]); |
|||
} |
|||
if(res.data.length < limit){ |
|||
this.getChatList[i]["haveHistory"] = 0; |
|||
} |
|||
|
|||
this.$set(this.getChatList, i, this.getChatList[i]) |
|||
}); |
|||
}, |
|||
// 跳转到聊天页面 |
|||
goToChat(key) { |
|||
this.navigateTo("/uni_modules/vrapile-im/pages/chat/chatFriend?data=" + key) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style scoped> |
|||
/* 重写外部nine-chat-home-001.scss可实现样式改变 */ |
|||
@import '/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss'; |
|||
@import '/static/style/nine-chat-home-001.scss'; |
|||
/* 重写外部nine-chat-home-001.scss可实现样式改变 */ |
|||
@import '/uni_modules/vrapile-im/static/style/nine-chat-home-001.scss'; |
|||
@import '/static/style/nine-chat-home-001.scss'; |
|||
</style> |
|||
@ -1,20 +1,20 @@ |
|||
{ |
|||
"pages": [ |
|||
// 消息 |
|||
{ |
|||
"path": "uni_modules/vrapile-im/pages/home/chatHome", |
|||
"style": { |
|||
"navigationBarTitleText": "消息", |
|||
"enablePullDownRefresh": false |
|||
} |
|||
}, |
|||
// 聊天 |
|||
{ |
|||
"path": "uni_modules/vrapile-im/pages/chat/chatFriend", |
|||
"style": { |
|||
"navigationBarTitleText": "聊天", |
|||
"enablePullDownRefresh": true |
|||
} |
|||
} |
|||
] |
|||
"pages": [ |
|||
// 消息 |
|||
{ |
|||
"path": "uni_modules/vrapile-im/pages/home/chatHome", |
|||
"style": { |
|||
"navigationBarTitleText": "消息", |
|||
"enablePullDownRefresh": false |
|||
} |
|||
}, |
|||
// 聊天 |
|||
{ |
|||
"path": "uni_modules/vrapile-im/pages/chat/chatFriend", |
|||
"style": { |
|||
"navigationBarTitleText": "聊天", |
|||
"enablePullDownRefresh": true |
|||
} |
|||
} |
|||
] |
|||
} |
|||
@ -1,165 +1,165 @@ |
|||
html, body, #app{ |
|||
height: 100%; |
|||
background-color: #f1f1f1; |
|||
height: 100%; |
|||
background-color: #f1f1f1; |
|||
} |
|||
.nine-content-001{ |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 750rpx; |
|||
height: calc(100vh - 0px); |
|||
margin: 0; |
|||
padding: 0; |
|||
background-color: #f1f1f1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 750rpx; |
|||
height: calc(100vh - 0px); |
|||
margin: 0; |
|||
padding: 0; |
|||
background-color: #f1f1f1; |
|||
} |
|||
.chat-body { |
|||
/* #ifdef MP-WEIXIN */ |
|||
background-color: #fff; |
|||
/* #endif */ |
|||
/* #ifdef MP-WEIXIN */ |
|||
background-color: #fff; |
|||
/* #endif */ |
|||
} |
|||
.chat-body-main{ |
|||
padding-top: 20rpx; |
|||
padding-left: 20rpx; |
|||
padding-right: 20rpx; |
|||
box-sizing: border-box; |
|||
-webkit-overflow-scrolling: touch; |
|||
padding-bottom: 100rpx; |
|||
padding-top: 20rpx; |
|||
padding-left: 20rpx; |
|||
padding-right: 20rpx; |
|||
box-sizing: border-box; |
|||
-webkit-overflow-scrolling: touch; |
|||
padding-bottom: 100rpx; |
|||
} |
|||
.chat-body-history{ |
|||
width: 100%; |
|||
height: 90rpx; |
|||
line-height: 90rpx; |
|||
font-size: 24rpx; |
|||
color: grey; |
|||
text-align: center; |
|||
width: 100%; |
|||
height: 90rpx; |
|||
line-height: 90rpx; |
|||
font-size: 24rpx; |
|||
color: grey; |
|||
text-align: center; |
|||
} |
|||
.chat-body-history-have{ |
|||
color: rgb(79, 172, 249); |
|||
color: rgb(79, 172, 249); |
|||
} |
|||
.chat-conversation{ |
|||
display: flex; |
|||
align-items: flex-start; |
|||
padding: 20rpx 5rpx; |
|||
word-break: break-all; |
|||
display: flex; |
|||
align-items: flex-start; |
|||
padding: 20rpx 5rpx; |
|||
word-break: break-all; |
|||
} |
|||
.chat-conversation-text{ |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: flex-start; |
|||
margin: 0 20rpx; |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: flex-start; |
|||
margin: 0 20rpx; |
|||
} |
|||
.chat-conversation-text-time{ |
|||
font-size: 10px; |
|||
color: gray; |
|||
font-size: 10px; |
|||
color: gray; |
|||
} |
|||
.chat-conversation-text-text{ |
|||
position: relative; |
|||
display: flex; |
|||
align-items: center; |
|||
max-width: 70%; |
|||
min-height: 45rpx; |
|||
padding: 15rpx 20rpx; |
|||
border-radius: 10rpx; |
|||
background-color: #FFF; |
|||
/* #ifdef MP-WEIXIN */ |
|||
background-color: #f1f1f1; |
|||
/* #endif */ |
|||
position: relative; |
|||
display: flex; |
|||
align-items: center; |
|||
max-width: 70%; |
|||
min-height: 45rpx; |
|||
padding: 15rpx 20rpx; |
|||
border-radius: 10rpx; |
|||
background-color: #FFF; |
|||
/* #ifdef MP-WEIXIN */ |
|||
background-color: #f1f1f1; |
|||
/* #endif */ |
|||
} |
|||
.chat-conversation-text-text::after { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 16rpx; |
|||
left: -35rpx; |
|||
border-width: 19rpx; |
|||
border-style: solid; |
|||
border-top-color: transparent; |
|||
border-left-color: transparent; |
|||
border-right-color: #FFF; |
|||
/* #ifdef MP-WEIXIN */ |
|||
border-right-color: #f1f1f1; |
|||
/* #endif */ |
|||
border-bottom-color: transparent; |
|||
content: ''; |
|||
position: absolute; |
|||
top: 16rpx; |
|||
left: -35rpx; |
|||
border-width: 19rpx; |
|||
border-style: solid; |
|||
border-top-color: transparent; |
|||
border-left-color: transparent; |
|||
border-right-color: #FFF; |
|||
/* #ifdef MP-WEIXIN */ |
|||
border-right-color: #f1f1f1; |
|||
/* #endif */ |
|||
border-bottom-color: transparent; |
|||
} |
|||
.chat-conversation-mine{ |
|||
align-items: flex-start; |
|||
flex-direction: row-reverse; |
|||
align-items: flex-start; |
|||
flex-direction: row-reverse; |
|||
} |
|||
.chat-conversation-mine .chat-conversation-text{ |
|||
align-items: flex-end; |
|||
align-items: flex-end; |
|||
} |
|||
.chat-conversation-mine .chat-conversation-text-time{ |
|||
text-align: right; |
|||
text-align: right; |
|||
} |
|||
.chat-conversation-mine .chat-conversation-text-text{ |
|||
background: #9ede86 !important; |
|||
background: #9ede86 !important; |
|||
} |
|||
.chat-conversation-mine .chat-conversation-text-text::after { |
|||
left: auto !important; |
|||
right: -35rpx !important; |
|||
border-left-color: #9ede86 !important; |
|||
border-right-color: transparent !important; |
|||
left: auto !important; |
|||
right: -35rpx !important; |
|||
border-left-color: #9ede86 !important; |
|||
border-right-color: transparent !important; |
|||
} |
|||
.chat-conversation-image{ |
|||
} |
|||
.chat-conversation-image-image{ |
|||
width: 80rpx; |
|||
height: 80rpx; |
|||
padding: 5rpx; |
|||
border-radius: 10rpx; |
|||
width: 80rpx; |
|||
height: 80rpx; |
|||
padding: 5rpx; |
|||
border-radius: 10rpx; |
|||
} |
|||
|
|||
.chat-footer { |
|||
position: fixed; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
height: 100rpx; |
|||
background-color: #fff; |
|||
display: flex; |
|||
/* #ifdef MP-WEIXIN */ |
|||
border-top: 1rpx solid #f1f1f1; |
|||
/* #endif */ |
|||
position: fixed; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
height: 100rpx; |
|||
background-color: #fff; |
|||
display: flex; |
|||
/* #ifdef MP-WEIXIN */ |
|||
border-top: 1rpx solid #f1f1f1; |
|||
/* #endif */ |
|||
} |
|||
.chat-footer-send{ |
|||
flex-grow: 1; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 0 10rpx; |
|||
flex-grow: 1; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 0 10rpx; |
|||
} |
|||
.chat-footer-send-image{ |
|||
padding: 0 10rpx; |
|||
width: 60rpx; |
|||
height: 60rpx; |
|||
padding: 0 10rpx; |
|||
width: 60rpx; |
|||
height: 60rpx; |
|||
} |
|||
.chat-footer-send-input{ |
|||
flex-grow: 1; |
|||
text-align: left; |
|||
padding: 15rpx; |
|||
border-radius: 5rpx; |
|||
background-color: #f9f9f9; |
|||
flex-grow: 1; |
|||
text-align: left; |
|||
padding: 15rpx; |
|||
border-radius: 5rpx; |
|||
background-color: #f9f9f9; |
|||
} |
|||
.chat-footer-send-say{ |
|||
flex-grow: 1; |
|||
text-align: center; |
|||
padding: 20rpx; |
|||
border-radius: 5rpx; |
|||
background-color: #f9f9f9; |
|||
flex-grow: 1; |
|||
text-align: center; |
|||
padding: 20rpx; |
|||
border-radius: 5rpx; |
|||
background-color: #f9f9f9; |
|||
} |
|||
.chat-footer-send-button{ |
|||
line-height: 65rpx; |
|||
margin: 0 10rpx; |
|||
color: #FFFFFF; |
|||
background-color: #0000ff; |
|||
border-radius: 10rpx; |
|||
line-height: 65rpx; |
|||
margin: 0 10rpx; |
|||
color: #FFFFFF; |
|||
background-color: #0000ff; |
|||
border-radius: 10rpx; |
|||
} |
|||
.chat-footer-send-button-span{ |
|||
padding: 0 25rpx; |
|||
padding: 0 25rpx; |
|||
} |
|||
|
|||
// 允许文本复制 |
|||
.nine-user-select { |
|||
cursor: auto; |
|||
-webkit-user-select: text; |
|||
user-select: text; |
|||
cursor: auto; |
|||
-webkit-user-select: text; |
|||
user-select: text; |
|||
} |
|||
@ -1,112 +1,112 @@ |
|||
html, body, #app{ |
|||
height: 100%; |
|||
background-color: #f1f1f1; |
|||
height: 100%; |
|||
background-color: #f1f1f1; |
|||
} |
|||
.nine-content-002{ |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 750rpx; |
|||
height: calc(100vh - 50px); |
|||
/* #ifndef H5 */ |
|||
height: calc(100vh - 0px); |
|||
/* #endif */ |
|||
margin: 0; |
|||
padding: 0; |
|||
background-color: #f1f1f1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 750rpx; |
|||
height: calc(100vh - 50px); |
|||
/* #ifndef H5 */ |
|||
height: calc(100vh - 0px); |
|||
/* #endif */ |
|||
margin: 0; |
|||
padding: 0; |
|||
background-color: #f1f1f1; |
|||
} |
|||
|
|||
.chat-search{ |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 5rpx; |
|||
background-color: #ffffff; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 5rpx; |
|||
background-color: #ffffff; |
|||
} |
|||
.chat-search-image{ |
|||
height: 45rpx; |
|||
line-height: 45rpx; |
|||
padding: 10rpx; |
|||
background-color: #f8f8f8; |
|||
height: 45rpx; |
|||
line-height: 45rpx; |
|||
padding: 10rpx; |
|||
background-color: #f8f8f8; |
|||
} |
|||
.chat-search-input{ |
|||
width: 100%; |
|||
height: 45rpx; |
|||
line-height: 45rpx; |
|||
padding: 10rpx; |
|||
font-size: 16px; |
|||
background-color: #f8f8f8; |
|||
width: 100%; |
|||
height: 45rpx; |
|||
line-height: 45rpx; |
|||
padding: 10rpx; |
|||
font-size: 16px; |
|||
background-color: #f8f8f8; |
|||
} |
|||
|
|||
.chat-list{ |
|||
flex: 1; |
|||
padding: 0; |
|||
overflow-y: auto; |
|||
flex: 1; |
|||
padding: 0; |
|||
overflow-y: auto; |
|||
} |
|||
.chat-list-item{ |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
margin: 2rpx 0; |
|||
padding: 15rpx 10rpx; |
|||
border-radius: 10rpx; |
|||
background-color: #ffffff; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
margin: 2rpx 0; |
|||
padding: 15rpx 10rpx; |
|||
border-radius: 10rpx; |
|||
background-color: #ffffff; |
|||
} |
|||
.chat-list-item-left{ |
|||
position: relative; |
|||
width: 84rpx; |
|||
height: 84rpx; |
|||
position: relative; |
|||
width: 84rpx; |
|||
height: 84rpx; |
|||
} |
|||
.chat-list-item-left-image{ |
|||
width: 82rpx; |
|||
height: 82rpx; |
|||
border: 1rpx solid #f1f1f1; |
|||
border-radius: 5rpx; |
|||
width: 82rpx; |
|||
height: 82rpx; |
|||
border: 1rpx solid #f1f1f1; |
|||
border-radius: 5rpx; |
|||
} |
|||
.chat-list-item-left-mark{ |
|||
position: absolute; |
|||
width: 30rpx; |
|||
top: -13rpx; |
|||
right: -13rpx; |
|||
padding: 1rpx; |
|||
border-radius: 50%; |
|||
font-size: 12px; |
|||
color: white; |
|||
background-color: red; |
|||
text-align: center; |
|||
position: absolute; |
|||
width: 30rpx; |
|||
top: -13rpx; |
|||
right: -13rpx; |
|||
padding: 1rpx; |
|||
border-radius: 50%; |
|||
font-size: 12px; |
|||
color: white; |
|||
background-color: red; |
|||
text-align: center; |
|||
} |
|||
|
|||
.chat-list-item-center{ |
|||
width: 450rpx; |
|||
margin: 0 20rpx; |
|||
width: 450rpx; |
|||
margin: 0 20rpx; |
|||
} |
|||
.chat-list-item-center-top{ |
|||
width: 450rpx; |
|||
font-size: 16px; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
width: 450rpx; |
|||
font-size: 16px; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
} |
|||
.chat-list-item-center-bottom{ |
|||
width: 450rpx; |
|||
font-size: 12px; |
|||
color: #969696; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
width: 450rpx; |
|||
font-size: 12px; |
|||
color: #969696; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
} |
|||
|
|||
.chat-list-item-right{ |
|||
width: 130rpx; |
|||
color: #a7a7a7; |
|||
width: 130rpx; |
|||
color: #a7a7a7; |
|||
} |
|||
.chat-list-item-right-top{ |
|||
font-size: 12px; |
|||
text-align: right; |
|||
font-size: 12px; |
|||
text-align: right; |
|||
} |
|||
.chat-list-item-right-bottom{ |
|||
padding-top: 15rpx; |
|||
text-align: right; |
|||
padding-top: 15rpx; |
|||
text-align: right; |
|||
} |
|||
.chat-list-item-right-bottom-image{ |
|||
width: 25rpx; |
|||
height: 30rpx; |
|||
width: 25rpx; |
|||
height: 30rpx; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue