Files
Yi.Admin/Yi.Bbs.Vue3/src/views/chathub/Index.vue

721 lines
16 KiB
Vue
Raw Normal View History

2024-04-04 19:28:18 +08:00
<script setup>
2024-04-06 18:28:32 +08:00
import { onMounted, ref, computed } from 'vue';
import { storeToRefs } from 'pinia'
import { getList as getChatUserList } from '@/apis/chatUserApi'
import { sendPersonalMessage,sendGroupMessage } from '@/apis/chatMessageApi'
2024-04-04 19:28:18 +08:00
import useChatStore from "@/stores/chat";
2024-04-06 18:28:32 +08:00
import useUserStore from "@/stores/user";
//聊天存储
const chatStore = useChatStore();
const { userList } = storeToRefs(chatStore);
//用户信息
const userStore = useUserStore();
//发送消息是否为空
const msgIsNullShow=ref(false)
//当前选择用户
const currentSelectUser = ref(null);
//当前输入框的值
const currentInputValue = ref("");
//临时存储的输入框根据用户id及组name、all组为keydata为value
const inputListDataStore = ref([{ key: "all", value: "" }]);
//当前聊天框显示的消息
const currentMsgContext = computed(() => {
if (selectIsAll()) {
return chatStore.allMsgContext;
}
else {
return chatStore.personalMsgContext.filter(x => {
//两个条件
//接收用户者id为对面id我发给他
//或者发送用户id为对面他发给我
return (x.receiveId == currentSelectUser.value.userId && x.sendUserId == userStore.id)||
(x.sendUserId == currentSelectUser.value.userId && x.receiveId == userStore.id);
});
}
});
//当前聊天框显示的名称
const currentHeaderName = computed(() => {
return currentSelectUser.value == null ? "官方学习交流群" : currentSelectUser.value.userName;
});
const currentUserItem = computed(() => {
return userList.value.filter(x=>x.userId!=useUserStore().id)
});
2024-04-04 19:28:18 +08:00
2024-04-06 18:28:32 +08:00
//初始化
onMounted(async () => {
2024-04-04 19:28:18 +08:00
chatStore.setUserList((await getChatUserList()).data);
})
2024-04-06 18:28:32 +08:00
/*-----方法-----*/
//当前选择的是否为全部
const selectIsAll = () => {
return currentSelectUser.value == null;
};
//输入框的值被更改
const changeInputValue = (inputValue) => {
currentInputValue.value = inputValue;
let index = -1;
let findKey = currentSelectUser.value?.userId
if (selectIsAll()) {
findKey = 'all'
}
index = inputListDataStore.value.findIndex(obj => obj.key == findKey);
inputListDataStore.value[index].value = currentInputValue.value;
}
//绑定的input改变事件
const updateInputValue = (event) => {
changeInputValue(event.target.value);
}
//获取输入框的值
const getCurrentInputValue = () => {
if (selectIsAll()) {
return inputListDataStore.value.filter(x => x.key == "all")[0].value;
} else {
//如果不存在初始存储值
if (!inputListDataStore.value.some(x => x.key == currentSelectUser.value.userId)) {
inputListDataStore.value.push({ key: currentSelectUser.value.userId, value: "" });
return "";
}
return inputListDataStore.value.filter(x => x.key == currentSelectUser.value.userId)[0].value;
}
};
//点击用户列表,
const onclickUserItem = (userInfo, isAllItem) => {
if (isAllItem) {
currentSelectUser.value = null;
}
else {
currentSelectUser.value = userInfo;
}
//填充临时存储的输入框
var value = getCurrentInputValue();
//更新当前的输入框
changeInputValue(value);
}
//点击发送按钮
const onclickSendMsg = () => {
console.log(currentInputValue.value ,"currentInputValue.value");
if(currentInputValue.value=="")
{
msgIsNullShow.value=true;
setTimeout(() => {
// 这里写上你想要3秒后执行的代码
msgIsNullShow.value=false;
}, 3000);
return;
}
if (selectIsAll()) {
onclickSendGroupMsg("all", currentInputValue.value);
}
else {
onclickSendPersonalMsg(currentSelectUser.value.userId, currentInputValue.value);
}
changeInputValue("");
}
//点击发送个人消息
const onclickSendPersonalMsg = (receiveId, msg) => {
//添加到本地存储
chatStore.addMsg({
messageType: "Personal",
sendUserId: userStore.id,
content: msg,
receiveId: receiveId
});
sendPersonalMessage({userId:receiveId,content:msg});
//调用接口发送消息
}
//点击发送群组消息按钮
const onclickSendGroupMsg = (groupName, msg) => {
//组还需区分是否给全部成员组
if (selectIsAll) {
//添加到本地存储,不需要,因为广播自己能够接收
// chatStore.addMsg({
// messageType: "All",
// sendUserId: userStore.id,
// content: msg
// });
//调用接口发送消息
sendGroupMessage({content:msg});
}
else {
alert("暂未实现");
}
}
2024-04-04 19:28:18 +08:00
</script>
2024-04-02 18:41:41 +08:00
<template>
2024-04-06 18:28:32 +08:00
2024-04-02 18:41:41 +08:00
<div class="body">
2024-04-02 23:24:10 +08:00
<div class="left">
<div class="icon">
<img src="@/assets/chat_images/icon.jpg">
2024-04-02 18:41:41 +08:00
</div>
2024-04-03 16:39:06 +08:00
<ul class="top-icon">
<li><img src="@/assets/chat_images/wechat.png" /></li>
<li><img src="@/assets/chat_images/addressBook.png" /></li>
<li><img src="@/assets/chat_images/collection.png" /></li>
<li><img src="@/assets/chat_images/file.png" /></li>
<li><img src="@/assets/chat_images/friend.png" /></li>
<li><img src="@/assets/chat_images/line.png" /></li>
<li><img src="@/assets/chat_images/look.png" /></li>
<li><img src="@/assets/chat_images/sou.png" /></li>
</ul>
<ul class="bottom-icon">
<li><img src="@/assets/chat_images/mini.png" /></li>
<li><img src="@/assets/chat_images/phone.png" /></li>
<li><img src="@/assets/chat_images/other.png" /></li>
</ul>
2024-04-02 23:24:10 +08:00
</div>
<div class="middle">
<div class="header">
2024-04-03 16:39:06 +08:00
<div class="header-div">
<div class="search">
<img src="@/assets/chat_images/search.png" />
<span>搜索</span>
</div>
<button type="button"> <img src="@/assets/chat_images/add.png" /></button>
</div>
</div>
<div class="user-list">
2024-04-06 18:28:32 +08:00
<div class="user-div" @click="onclickUserItem(null, true)"
:class="{ 'select-user-item': currentSelectUser == null }">
2024-04-03 16:39:06 +08:00
<div class="user-div-left">
2024-04-06 18:28:32 +08:00
<img src="@/assets/chat_images/yilogo.png" />
2024-04-03 16:39:06 +08:00
<div class="user-name-msg">
2024-04-04 19:28:18 +08:00
<p class="font-name">官方学习交流群</p>
<p class="font-msg">冲冲冲</p>
2024-04-03 16:39:06 +08:00
</div>
</div>
<div class=" user-div-right">
10:28
</div>
</div>
2024-04-06 18:28:32 +08:00
<div v-for="(item, i) in currentUserItem" :key="i" @click="onclickUserItem(item, false)" class="user-div"
:class="{ 'select-user-item': currentSelectUser?.userId == item.userId }">
2024-04-03 16:39:06 +08:00
<div class="user-div-left">
<img src="@/assets/chat_images/friendicon.jpg" />
<div class="user-name-msg">
2024-04-06 18:28:32 +08:00
<p class="font-name">{{ item.userName }}</p>
2024-04-03 16:39:06 +08:00
<p class="font-msg">现在感觉怎么样</p>
</div>
</div>
<div class=" user-div-right">
10:28
</div>
</div>
2024-04-02 18:41:41 +08:00
</div>
2024-04-02 23:24:10 +08:00
</div>
<div class="right">
2024-04-03 16:39:06 +08:00
<div class="header">
2024-04-06 18:28:32 +08:00
<div class="header-left">{{ currentHeaderName }}</div>
2024-04-03 16:39:06 +08:00
<div class="header-right">
<div>
<ul>
<li><img src="@/assets/chat_images/fixed.png" /></li>
<li><img src="@/assets/chat_images/min.png" /></li>
<li><img src="@/assets/chat_images/max.png" /></li>
<li><img src="@/assets/chat_images/close.png" /></li>
</ul>
</div>
<div class="more"><img src="@/assets/chat_images/other2.png" /></div>
</div>
</div>
<div class="content">
2024-04-06 18:28:32 +08:00
<div v-for="(item, i) in currentMsgContext" :key="i">
<div class="content-myself content-common" v-if="item.sendUserId == userStore.id">
<div class="content-myself-msg content-msg-common ">{{ item.content }}</div>
2024-04-03 16:39:06 +08:00
<img src="@/assets/chat_images/icon.jpg" />
</div>
2024-04-06 18:28:32 +08:00
<div class="content-others content-common" v-else>
<img src="@/assets/chat_images/friendicon.jpg" />
<div class="content-others-msg content-msg-common ">{{ item.content }}</div>
</div>
2024-04-03 16:39:06 +08:00
</div>
</div>
<div class="bottom">
<div class="bottom-tool">
2024-04-06 18:28:32 +08:00
<ul class="ul-left">
<li><img src="@/assets/chat_images/emoji.png" /></li>
<li><img src="@/assets/chat_images/sendFile.png" /></li>
<li><img src="@/assets/chat_images/screenshot.png" /></li>
<li><img src="@/assets/chat_images/chatHistory.png" /></li>
</ul>
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
<ul class="ul-right">
<li><img src="@/assets/chat_images/landline.png" /></li>
<li><img src="@/assets/chat_images/videoChat.png" /></li>
</ul>
2024-04-02 18:41:41 +08:00
2024-04-06 18:28:32 +08:00
</div>
<!-- <div class="bottom-input" contenteditable="true" @input="updateInputValue"> -->
<!-- <div class="bottom-input" contenteditable="true" @input="updateInputValue">
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
</div> -->
<textarea class="bottom-input" v-model="currentInputValue" @input="updateInputValue" @keyup.enter="onclickSendMsg()">
</textarea>
<div class="bottom-send">
<div class="msg-null" v-show="msgIsNullShow">不能发送空白信息</div>
<button @click="onclickSendMsg()">
发送(S)
</button>
2024-04-03 16:39:06 +08:00
</div>
</div>
2024-04-06 18:28:32 +08:00
</div>
</div>
2024-04-02 18:41:41 +08:00
</template>
<style scoped lang="scss">
.body {
2024-04-02 23:24:10 +08:00
height: 790px;
width: 1400px;
2024-04-02 18:41:41 +08:00
display: flex;
justify-content: center;
box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
}
2024-04-02 23:24:10 +08:00
2024-04-06 18:28:32 +08:00
.select-user-item {
background-color: #C8C8CA !important;
}
2024-04-02 18:41:41 +08:00
.left {
background-color: #2a2a2a;
width: 70px;
2024-04-02 23:24:10 +08:00
padding: 46px 10px 0 10px;
.icon {
background-color: burlywood;
height: 46px;
width: 46px;
2024-04-03 16:39:06 +08:00
img {
2024-04-02 23:24:10 +08:00
height: 100%;
width: 100%;
}
}
2024-04-02 18:41:41 +08:00
}
.middle {
background-color: #dadbdc;
width: 380px;
2024-04-02 23:24:10 +08:00
2024-04-02 18:41:41 +08:00
.header {
height: 75px;
background: #f7f7f7;
2024-04-03 16:39:06 +08:00
padding: 26px 0 26px 0;
.header-div {
background-color: #F7F7F7;
2024-04-02 23:24:10 +08:00
height: 30px;
width: 338px;
2024-04-03 16:39:06 +08:00
margin: auto;
display: flex;
justify-content: space-between;
.search {
width: 300px;
height: 100%;
background-color: #E2E2E2;
border-radius: 5px;
padding: 5px;
img {
height: 16px;
width: 16px;
}
span {
margin-left: 10px;
font-size: 14px;
color: #818181;
margin-bottom: 5px;
vertical-align: top;
}
}
button {
margin-left: 10px;
width: 30px;
background-color: #E2E2E2;
border-radius: 5px;
padding: 5px 3px;
img {
height: 100%;
width: 100%;
}
}
2024-04-02 23:24:10 +08:00
}
2024-04-03 16:39:06 +08:00
2024-04-02 18:41:41 +08:00
}
2024-04-02 23:24:10 +08:00
2024-04-03 16:39:06 +08:00
.user-list::-webkit-scrollbar-thumb {
background-color: #BEBCBA;
/* 滚动条滑块颜色 */
}
.user-list::-webkit-scrollbar {
width: 8px;
/* 滚动条宽度 */
height: 10px;
/* 滚动条高度 */
}
.user-list {
height: calc(100% - 75px);
overflow-y: auto;
/* 只启用垂直方向滚动条 */
.user-div {
display: flex;
justify-content: space-between;
height: 80px;
width: 100%;
background-color: #EAE8E7;
padding: 16px;
&-left {
height: 100%;
display: flex;
.user-name-msg {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 0 10px;
.font-name {
font-size: 20px;
}
.font-msg {
font-size: 15px;
color: #999999;
}
}
img {
height: 100%;
}
}
&-right {
font-size: 15px;
color: #999999;
}
}
.user-div:hover {
background-color: #D9D8D8;
}
}
2024-04-02 18:41:41 +08:00
}
2024-04-02 23:24:10 +08:00
2024-04-02 18:41:41 +08:00
.right {
background-color: #f5f5f5;
width: 950px;
2024-04-02 23:24:10 +08:00
2024-04-02 18:41:41 +08:00
.header {
height: 75px;
background: #f7f7f7;
border: 1px solid #e7e7e7;
2024-04-03 16:39:06 +08:00
display: flex;
justify-content: space-between;
.header-left {
padding: 25px;
font-size: 25px;
align-content: center;
}
.header-right {
ul {
display: flex;
li {
padding: 8px 12.5px 10px 12.5px;
img {
height: 15px;
width: 15px;
}
}
}
.more {
padding: 0px 12.5px;
display: flex;
justify-content: flex-end;
img {
height: 18px;
width: 18px;
}
}
}
2024-04-02 18:41:41 +08:00
}
2024-04-02 23:24:10 +08:00
2024-04-02 18:41:41 +08:00
.content {
2024-04-03 16:39:06 +08:00
overflow-y: auto;
/* 只启用垂直方向滚动条 */
height: 555px;
padding: 20px 40px;
2024-04-02 18:41:41 +08:00
}
2024-04-02 23:24:10 +08:00
2024-04-02 18:41:41 +08:00
.bottom {
2024-04-03 16:39:06 +08:00
height: calc(100% - 630px);
2024-04-02 18:41:41 +08:00
background: #f7f7f7;
2024-04-03 16:39:06 +08:00
border-top: 1.5px solid #e7e7e7;
padding: 15px 35px;
&-tool {
display: flex;
2024-04-06 18:28:32 +08:00
justify-content: space-between;
2024-04-03 16:39:06 +08:00
height: 22px;
2024-04-06 18:28:32 +08:00
2024-04-03 16:39:06 +08:00
.ul-left {
2024-04-06 18:28:32 +08:00
display: flex;
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
li {
width: 22px;
height: 22px;
margin-right: 20px;
}
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
img {
width: 100%;
height: 100%;
2024-04-03 16:39:06 +08:00
}
2024-04-06 18:28:32 +08:00
}
2024-04-03 16:39:06 +08:00
.ul-right {
2024-04-06 18:28:32 +08:00
display: flex;
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
li {
width: 22px;
height: 22px;
margin-right: 20px;
}
2024-04-03 16:39:06 +08:00
2024-04-06 18:28:32 +08:00
img {
width: 100%;
height: 100%;
2024-04-03 16:39:06 +08:00
}
}
2024-04-06 18:28:32 +08:00
}
2024-04-03 16:39:06 +08:00
&-input {
2024-04-06 18:28:32 +08:00
font-family: "Microsoft YaHei", sans-serif;
2024-04-03 16:39:06 +08:00
height: 70px;
width: 100%;
overflow-y: auto;
padding: 10px 0;
font-size: 18px;
2024-04-06 18:28:32 +08:00
background: #F7F7F7;
border: none;
resize: none;
outline: none;
2024-04-03 16:39:06 +08:00
}
&-send {
display: flex;
justify-content: flex-end;
button {
width: 126px;
height: 40px;
background-color: #E9E9E9;
color: #06AE56;
border-radius: 5px;
font-size: 18px;
}
button:hover {
background-color: #D2D2D2;
}
}
2024-04-02 18:41:41 +08:00
}
}
2024-04-02 23:24:10 +08:00
2024-04-03 16:39:06 +08:00
.top-icon {
2024-04-02 23:24:10 +08:00
margin-top: 32px;
2024-04-03 16:39:06 +08:00
li {
2024-04-02 23:24:10 +08:00
cursor: pointer;
text-align: center;
2024-04-03 16:39:06 +08:00
margin-bottom: 24px;
img {
2024-04-02 23:24:10 +08:00
height: 24px;
width: 24px;
2024-04-03 16:39:06 +08:00
2024-04-02 23:24:10 +08:00
}
}
}
2024-04-03 16:39:06 +08:00
.bottom-icon {
margin-top: 125px;
li {
2024-04-02 23:24:10 +08:00
cursor: pointer;
text-align: center;
2024-04-03 16:39:06 +08:00
margin-bottom: 24px;
img {
2024-04-02 23:24:10 +08:00
height: 24px;
width: 24px;
2024-04-03 16:39:06 +08:00
2024-04-02 23:24:10 +08:00
}
}
}
2024-04-03 16:39:06 +08:00
.content-common {
display: flex;
2024-04-06 18:28:32 +08:00
margin-bottom: 18px;
2024-04-03 16:39:06 +08:00
img {
height: 45px;
width: 45px;
}
}
.content-msg-common {
display: flex;
align-content: center;
flex-wrap: wrap;
position: relative;
margin: 0 15px;
padding: 5px 15px;
text-align: center;
font-size: 18px;
border-radius: 5px;
}
.content-myself {
justify-content: flex-end;
}
.content-myself-msg:hover {
background-color: #89D961;
}
.content-myself-msg {
background-color: #95EC69;
}
.content-myself-msg:hover:after {
border-left: 10px solid #89D961;
}
.content-others {
justify-content: flex-start;
}
.content-others-msg {
background-color: #FFFFFF;
}
.content-others-msg:hover {
background-color: #EBEBEB;
}
.content-others-msg:hover:after {
border-right: 10px solid #EBEBEB;
}
.content-myself-msg:after {
content: '';
position: absolute;
width: 0;
height: 0;
/* 箭头靠右边 */
top: 13px;
right: -10px;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid #97EC6F;
}
.content-others-msg:after {
/* 箭头靠左边 */
content: '';
position: absolute;
width: 0;
height: 0;
top: 13px;
left: -10px;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid #FFFFFF;
2024-04-06 18:28:32 +08:00
}
.msg-null{
width: 140px;
height: 41px;
background-color: #FFFFFF;
position: relative;
left: 132px;
bottom: 60px;
border-radius: 5px;
// border: 2px solid #E5E5E5;
display: flex;
align-content: center;
justify-content: center;
flex-wrap: wrap;
font-size: 14px;
}
.msg-null:after {
/* 箭头靠下边 */
content: "";
position: absolute;
width: 0;
height: 0;
top: 40px;
left: 80px;
border-top: 10px solid #FFFFFF;
border-bottom: 10px solid transparent;
border-right: 10px solid transparent;
border-left: 10px solid transparent;
2024-04-03 16:39:06 +08:00
}
2024-04-02 18:41:41 +08:00
</style>