Browse Source

web端样式风格调整

master
blue 2 years ago
parent
commit
eb90c67802
  1. 8
      README.md
  2. 98
      im-ui/src/App.vue
  3. 38
      im-ui/src/assets/iconfont/iconfont.css
  4. BIN
      im-ui/src/assets/iconfont/iconfont.ttf
  5. 51
      im-ui/src/components/chat/ChatBox.vue
  6. 10
      im-ui/src/components/chat/ChatItem.vue
  7. 9
      im-ui/src/components/friend/AddFriend.vue
  8. 8
      im-ui/src/components/friend/FriendItem.vue
  9. 13
      im-ui/src/components/group/AddGroupMember.vue
  10. 8
      im-ui/src/components/group/GroupItem.vue
  11. 3
      im-ui/src/components/setting/Setting.vue
  12. 16
      im-ui/src/view/Chat.vue
  13. 80
      im-ui/src/view/Friend.vue
  14. 74
      im-ui/src/view/Group.vue
  15. 66
      im-ui/src/view/Home.vue
  16. 9
      im-ui/src/view/Login.vue

8
README.md

@ -249,13 +249,6 @@ wsApi.onClose((e) => {
欢迎进群与小伙们一起交流, **申请加群前请务必先star哦** 欢迎进群与小伙们一起交流, **申请加群前请务必先star哦**
#### 嘿嘿
![输入图片说明](%E6%88%AA%E5%9B%BE/%E5%BE%AE%E4%BF%A1%E6%94%B6%E6%AC%BE%E7%A0%81.png)
悄悄放个二维码在这,宝子们..你懂我意思吧
#### 点下star吧 #### 点下star吧
如果项目对您有帮助,请点亮右上方的star,支持一下作者吧! 如果项目对您有帮助,请点亮右上方的star,支持一下作者吧!
@ -264,4 +257,5 @@ wsApi.onClose((e) => {
1. 本系统允许用于商业用途,且不收费(自愿投币)。**但切记不要用于任何非法用途** ,本软件作者不会为此承担任何责任 1. 本系统允许用于商业用途,且不收费(自愿投币)。**但切记不要用于任何非法用途** ,本软件作者不会为此承担任何责任
1. 基于本系统二次开发后再次开源的项目,请注明引用出处,以避免引发不必要的误会 1. 基于本系统二次开发后再次开源的项目,请注明引用出处,以避免引发不必要的误会
1. 如果您也想体验开源(bei bai piao)的快感,成为本项目的贡献者,欢迎提交PR。开发前最好提前联系作者,避免功能重复开发 1. 如果您也想体验开源(bei bai piao)的快感,成为本项目的贡献者,欢迎提交PR。开发前最好提前联系作者,避免功能重复开发
1. 作者目前不打算接项目,如果能接受1k/天以上的报价,也可以聊聊

98
im-ui/src/App.vue

@ -1,33 +1,89 @@
<template> <template>
<div id="app"> <div id="app">
<router-view></router-view> <router-view></router-view>
</div> </div>
</template> </template>
<script> <script>
export default {
name: 'App',
components: {}
}
</script>
<style lang="scss">
@import './assets/style/global.css';
export default { #app {
name: 'App', font-family: 'Avenir', Helvetica, Arial, sans-serif;
components: { -webkit-font-smoothing: antialiased;
} -moz-osx-font-smoothing: grayscale;
color: #2c3e50;
position: absolute;
height: 100%;
width: 100%;
} }
</script>
<style> .el-message {
@import './assets/style/global.css'; z-index: 99999999 !important;
}
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif; .el-scrollbar__thumb {
-webkit-font-smoothing: antialiased; background-color: #A0A8AF !important;
-moz-osx-font-smoothing: grayscale; }
color: #2c3e50;
position: absolute; .el-dialog {
height: 100%; border-radius: 8px !important;
width: 100%; overflow: hidden !important;
}
.el-dialog__header {
background-color: #5870e6 !important;
}
.el-dialog__title {
color: #f8f8f8 !important;
}
.el-dialog__close {
color: white !important;
font-size: 20px;
}
.el-checkbox__inner {
border-radius: 50% !important;
}
.el-input__inner {
border-radius: 5px !important;
border: #587FF0 1px solid !important;
}
.el-textarea__inner{
border-radius: 5px !important;
border: #587FF0 1px solid !important;
}
.el-icon-search {
color:#587FF0 !important;
}
.el-button--primary {
background-color: #687Ff0 !important;
border-color: #687Ff0 !important;
}
.el-button--success {
background-color: #4cae1b !important;
border-color: #4cae1b !important;
}
.el-button--danger {
background-color: #ea4949 !important;
border-color: #ea4949 !important;
} }
.el-message { .el-button {
z-index: 99999999 !important; padding: 8px 15px !important;
} }
</style> </style>

38
im-ui/src/assets/iconfont/iconfont.css

@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 3791506 */ font-family: "iconfont"; /* Project id 3791506 */
src: url('iconfont.ttf?t=1711892447736') format('truetype'); src: url('iconfont.ttf?t=1714220334746') format('truetype');
} }
.iconfont { .iconfont {
@ -11,6 +11,18 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-chat:before {
content: "\e600";
}
.icon-setting:before {
content: "\e620";
}
.icon-friend:before {
content: "\e604";
}
.icon-exit:before { .icon-exit:before {
content: "\e9e4"; content: "\e9e4";
} }
@ -31,34 +43,14 @@
content: "\e61a"; content: "\e61a";
} }
.icon-biaoqing:before { .icon-emoji:before {
content: "\e60c"; content: "\e60c";
} }
.icon-youyinpin:before { .icon-group:before {
content: "\e649";
}
.icon-audio:before {
content: "\e800";
}
.icon-group_fill:before {
content: "\e7f4"; content: "\e7f4";
} }
.icon-yinpin:before {
content: "\e68a";
}
.icon-emoji:before {
content: "\e6f6";
}
.icon-voiceprint:before {
content: "\e953";
}
.icon-phone-reject:before { .icon-phone-reject:before {
content: "\e605"; content: "\e605";
} }

BIN
im-ui/src/assets/iconfont/iconfont.ttf

Binary file not shown.

51
im-ui/src/components/chat/ChatBox.vue

@ -1,7 +1,7 @@
<template> <template>
<div class="chat-box" @click="closeRefBox()" @mousemove="readedMessage()"> <div class="chat-box" @click="closeRefBox()" @mousemove="readedMessage()">
<el-container> <el-container>
<el-header height="60px"> <el-header height="56px">
<span>{{ title }}</span> <span>{{ title }}</span>
<span title="群聊信息" v-show="this.chat.type == 'GROUP'" class="btn-side el-icon-more" <span title="群聊信息" v-show="this.chat.type == 'GROUP'" class="btn-side el-icon-more"
@click="showSide = !showSide"></span> @click="showSide = !showSide"></span>
@ -25,7 +25,7 @@
</el-main> </el-main>
<el-footer height="240px" class="im-chat-footer"> <el-footer height="240px" class="im-chat-footer">
<div class="chat-tool-bar"> <div class="chat-tool-bar">
<div title="表情" class="icon iconfont icon-biaoqing" ref="emotion" <div title="表情" class="icon iconfont icon-emoji" ref="emotion"
@click.stop="showEmotionBox()"> @click.stop="showEmotionBox()">
</div> </div>
<div title="发送图片"> <div title="发送图片">
@ -58,7 +58,7 @@
<div contenteditable="true" v-show="!sendImageUrl" ref="editBox" class="send-text-area" <div contenteditable="true" v-show="!sendImageUrl" ref="editBox" class="send-text-area"
:disabled="lockMessage" @paste.prevent="onEditorPaste" :disabled="lockMessage" @paste.prevent="onEditorPaste"
@compositionstart="onEditorCompositionStart" @compositionend="onEditorCompositionEnd" @compositionstart="onEditorCompositionStart" @compositionend="onEditorCompositionEnd"
@input="onEditorInput" :placeholder="isReceipt ? '【回执消息】' : ''" @blur="onEditBoxBlur()" @input="onEditorInput" :placeholder="placeholder" @blur="onEditBoxBlur()"
@keydown.down="onKeyDown" @keydown.up="onKeyUp" @keydown.enter.prevent="onKeyEnter">x @keydown.down="onKeyDown" @keydown.up="onKeyUp" @keydown.enter.prevent="onKeyEnter">x
</div> </div>
@ -123,6 +123,7 @@ export default {
groupMembers: [], groupMembers: [],
sendImageUrl: "", sendImageUrl: "",
sendImageFile: "", sendImageFile: "",
placeholder: "",
isReceipt: true, isReceipt: true,
showVoice: false, // showVoice: false, //
showSide: false, // showSide: false, //
@ -191,6 +192,7 @@ export default {
this.atSearchText = this.focusNode.textContent.substring(stIdx + 1); this.atSearchText = this.focusNode.textContent.substring(stIdx + 1);
} }
} }
this.refreshPlaceHolder();
}, },
onEditorCompositionStart() { onEditorCompositionStart() {
@ -238,6 +240,7 @@ export default {
}, },
onSwitchReceipt() { onSwitchReceipt() {
this.isReceipt = !this.isReceipt; this.isReceipt = !this.isReceipt;
this.refreshPlaceHolder();
}, },
createSendText() { createSendText() {
let sendText = this.isReceipt ? "【回执消息】" : ""; let sendText = this.isReceipt ? "【回执消息】" : "";
@ -684,6 +687,17 @@ export default {
let div = document.getElementById("chatScrollBox"); let div = document.getElementById("chatScrollBox");
div.scrollTop = div.scrollHeight; div.scrollTop = div.scrollHeight;
}); });
},
refreshPlaceHolder(){
console.log("placeholder")
if(this.isReceipt){
this.placeholder = "【回执消息】"
}else if(this.$refs.editBox && this.$refs.editBox.innerHTML){
this.placeholder = ""
}else{
this.placeholder = "聊点什么吧~";
}
} }
}, },
computed: { computed: {
@ -710,6 +724,7 @@ export default {
} }
return this.chat.messages.length; return this.chat.messages.length;
} }
}, },
watch: { watch: {
chat: { chat: {
@ -735,6 +750,8 @@ export default {
this.resetEditor(); this.resetEditor();
// //
this.isReceipt = false; this.isReceipt = false;
// placeholder
this.refreshPlaceHolder();
} }
}, },
immediate: true immediate: true
@ -763,30 +780,26 @@ export default {
border: #dddddd solid 1px; border: #dddddd solid 1px;
.el-header { .el-header {
padding: 5px; padding: 3px;
background-color: white; background-color: #5870e6;
line-height: 50px; line-height: 50px;
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
border: #dddddd solid 1px; color: #f8f8f8;
.btn-side { .btn-side {
position: absolute; position: absolute;
right: 20px; right: 20px;
line-height: 60px; line-height: 50px;
font-size: 22px; font-size: 25px;
cursor: pointer; cursor: pointer;
&:hover {
font-size: 30px;
}
} }
} }
.im-chat-main { .im-chat-main {
padding: 0; padding: 0;
border: #dddddd solid 1px;
.im-chat-box { .im-chat-box {
>ul { >ul {
padding: 0 20px; padding: 0 20px;
@ -802,23 +815,21 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 0; padding: 0;
border: #dddddd solid 1px;
.chat-tool-bar { .chat-tool-bar {
display: flex; display: flex;
position: relative; position: relative;
width: 100%; width: 100%;
height: 40px; height: 40px;
text-align: left; text-align: left;
box-sizing: border-box; box-sizing: border-box;
border: #dddddd solid 1px; border-top: #ccc solid 1px;
padding: 2px; padding: 2px;
background-color: #E8F2FF;
>div { >div {
font-size: 22px; font-size: 22px;
cursor: pointer; cursor: pointer;
color: #333333; color: black;
line-height: 34px; line-height: 34px;
width: 34px; width: 34px;
height: 34px; height: 34px;

10
im-ui/src/components/chat/ChatItem.vue

@ -100,19 +100,19 @@
padding: 5px; padding: 5px;
padding-left: 10px; padding-left: 10px;
align-items: center; align-items: center;
background-color: #fafafa; background-color: white;
white-space: nowrap; white-space: nowrap;
color: black; color: black;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: #eeeeee; background-color: #F8FAFF;
} }
&.active { &.active {
background-color: #e8e8f0; background-color: #F4F9FF;
} }
.chat-left { .chat-left {
position: relative; position: relative;
display: flex; display: flex;

9
im-ui/src/components/friend/AddFriend.vue

@ -1,7 +1,8 @@
<template> <template>
<el-dialog title="添加好友" :visible.sync="dialogVisible" width="30%" :before-close="onClose"> <el-dialog title="添加好友" :visible.sync="dialogVisible" width="30%" :before-close="onClose">
<el-input placeholder="输入用户名或昵称,最多展示20条" class="input-with-select" v-model="searchText" @keyup.enter.native="onSearch()"> <el-input placeholder="输入用户名或昵称进行,最多展示20条" class="input-with-select" v-model="searchText" @keyup.enter.native="onSearch()">
<el-button slot="append" icon="el-icon-search" @click="onSearch()"></el-button> <i class="el-icon-search el-input__icon" slot="suffix"
@click="onSearch()"> </i>
</el-input> </el-input>
<el-scrollbar style="height:400px"> <el-scrollbar style="height:400px">
<div v-for="(user) in users" :key="user.id" v-show="user.id != $store.state.userStore.userInfo.id"> <div v-for="(user) in users" :key="user.id" v-show="user.id != $store.state.userStore.userInfo.id">
@ -21,8 +22,8 @@
<div>昵称:{{user.nickName}}</div> <div>昵称:{{user.nickName}}</div>
</div> </div>
</div> </div>
<el-button type="success" size="small" v-show="!isFriend(user.id)" plain @click="onAddFriend(user)">添加</el-button> <el-button type="success" size="mini" v-show="!isFriend(user.id)" @click="onAddFriend(user)">添加</el-button>
<el-button type="info" size="small" v-show="isFriend(user.id)" plain disabled>已添加</el-button> <el-button type="info" size="mini" v-show="isFriend(user.id)" plain disabled>已添加</el-button>
</div> </div>
</div> </div>
</el-scrollbar> </el-scrollbar>

8
im-ui/src/components/friend/FriendItem.vue

@ -95,13 +95,13 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: #eeeeee; background-color: #F8FAFF;
} }
&.active { &.active {
background-color: #dddddd; background-color: #F4F9FF;
} }
.friend-avatar { .friend-avatar {
display: flex; display: flex;
justify-content: center; justify-content: center;

13
im-ui/src/components/group/AddGroupMember.vue

@ -2,9 +2,9 @@
<el-dialog title="邀请好友" :visible.sync="visible" width="50%" :before-close="onClose"> <el-dialog title="邀请好友" :visible.sync="visible" width="50%" :before-close="onClose">
<div class="agm-container"> <div class="agm-container">
<div class="agm-l-box"> <div class="agm-l-box">
<el-input width="200px" placeholder="搜索好友" class="input-with-select" v-model="searchText" <el-input placeholder="搜索好友" v-model="searchText"
@keyup.enter.native="onSearch()"> @keyup.enter.native="onSearch()">
<el-button slot="append" icon="el-icon-search" @click="onSearch()"></el-button> <i class="el-icon-search el-input__icon" slot="suffix"> </i>
</el-input> </el-input>
<el-scrollbar style="height:400px;"> <el-scrollbar style="height:400px;">
<div v-for="(friend,index) in friends" :key="friend.id"> <div v-for="(friend,index) in friends" :key="friend.id">
@ -132,9 +132,10 @@
display: flex; display: flex;
.agm-l-box { .agm-l-box {
flex: 1; flex: 1;
border: #53a0e79c solid 1px; border: #587FF0 solid 1px;
border-radius: 5px; border-radius: 5px;
overflow: hidden; overflow: hidden;
.el-checkbox { .el-checkbox {
display: flex; display: flex;
align-items: center; align-items: center;
@ -171,14 +172,14 @@
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 20px; font-size: 20px;
padding: 5px; padding: 10px;
font-weight: 600; font-weight: 600;
color: #53a0e7cc; color: #687Ff0;
} }
.agm-r-box { .agm-r-box {
flex: 1; flex: 1;
border: #53a0e79c solid 1px; border: #587FF0 solid 1px;
border-radius: 5px; border-radius: 5px;
.agm-select-tip { .agm-select-tip {

8
im-ui/src/components/group/GroupItem.vue

@ -41,14 +41,14 @@
padding: 5px; padding: 5px;
padding-left: 10px; padding-left: 10px;
align-items: center; align-items: center;
background-color: #fafafa; background-color: white;
white-space: nowrap; white-space: nowrap;
&:hover { &:hover {
background-color: #eeeeee; background-color: #F8FAFF;
} }
&.active { &.active {
background-color: #dddddd; background-color: #F4F9FF;
} }
.group-avatar { .group-avatar {
@ -63,7 +63,7 @@
line-height: 50px; line-height: 50px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
font-size: 14px; font-size: 15px;
font-weight: 600; font-weight: 600;
} }
} }

3
im-ui/src/components/setting/Setting.vue

@ -1,6 +1,6 @@
<template> <template>
<el-dialog class="setting" title="设置" :visible.sync="visible" width="500px" :before-close="onClose"> <el-dialog class="setting" title="设置" :visible.sync="visible" width="500px" :before-close="onClose">
<el-form :model="userInfo" label-width="80px" :rules="rules" ref="settingForm"> <el-form :model="userInfo" label-width="70px" :rules="rules" ref="settingForm">
<el-form-item label="头像"> <el-form-item label="头像">
<file-upload class="avatar-uploader" <file-upload class="avatar-uploader"
:action="imageAction" :action="imageAction"
@ -108,6 +108,7 @@
<style lang="scss" > <style lang="scss" >
.setting { .setting {
.avatar-uploader { .avatar-uploader {
.el-upload { .el-upload {

16
im-ui/src/view/Chat.vue

@ -2,8 +2,8 @@
<el-container class="chat-page"> <el-container class="chat-page">
<el-aside width="260px" class="chat-list-box"> <el-aside width="260px" class="chat-list-box">
<div class="chat-list-header"> <div class="chat-list-header">
<el-input width="200px" placeholder="搜索" v-model="searchText"> <el-input class="search-text" placeholder="搜索" v-model="searchText">
<el-button slot="append" icon="el-icon-search"></el-button> <i class="el-icon-search el-input__icon" slot="prefix"> </i>
</el-input> </el-input>
</div> </div>
<div class="chat-list-loadding" v-if="loading" v-loading="true" element-loading-text="消息接收中..." <div class="chat-list-loadding" v-if="loading" v-loading="true" element-loading-text="消息接收中..."
@ -74,9 +74,15 @@
width: 3rem; width: 3rem;
.chat-list-header { .chat-list-header {
padding: 5px; padding: 3px 8px;
background-color: white; background-color: #5870e6;
line-height: 50px; line-height: 50px;
.el-input__inner {
border-radius: 10px !important;
background-color: #F8F8F8;
}
} }
.chat-list-loadding{ .chat-list-loadding{
@ -90,6 +96,8 @@
.chat-list-items { .chat-list-items {
flex: 1; flex: 1;
background: #F8F8F8;
margin: 0 3px;
} }
} }
} }

80
im-ui/src/view/Friend.vue

@ -2,19 +2,16 @@
<el-container class="friend-page"> <el-container class="friend-page">
<el-aside width="260px" class="friend-list-box"> <el-aside width="260px" class="friend-list-box">
<div class="friend-list-header"> <div class="friend-list-header">
<div class="friend-list-search"> <el-input class="search-text" placeholder="搜索" v-model="searchText">
<el-input width="200px" placeholder="搜索好友" v-model="searchText"> <i class="el-icon-search el-input__icon" slot="prefix"> </i>
<el-button slot="append" icon="el-icon-search"></el-button> </el-input>
</el-input> <el-button plain class="add-btn" icon="el-icon-plus" title="添加好友"
</div> @click="onShowAddFriend()"></el-button>
<el-button plain icon="el-icon-plus" style="border: none; padding:12px; font-size: 20px;color: black;" <add-friend :dialogVisible="showAddFriend" @close="onCloseAddFriend"></add-friend>
title="添加好友" @click="onShowAddFriend()"></el-button>
<add-friend :dialogVisible="showAddFriend" @close="onCloseAddFriend">
</add-friend>
</div> </div>
<el-scrollbar class="friend-list-items"> <el-scrollbar class="friend-list-items">
<div v-for="(friend,index) in $store.state.friendStore.friends" :key="index"> <div v-for="(friend,index) in $store.state.friendStore.friends" :key="index">
<friend-item v-show="friend.nickName.startsWith(searchText)" :index="index" <friend-item v-show="friend.nickName.startsWith(searchText)" :index="index"
:active="friend === $store.state.friendStore.activeFriend" @chat="onSendMessage(friend)" :active="friend === $store.state.friendStore.activeFriend" @chat="onSendMessage(friend)"
@delete="onDelItem(friend,index)" @click.native="onActiveItem(friend,index)"> @delete="onDelItem(friend,index)" @click.native="onActiveItem(friend,index)">
</friend-item> </friend-item>
@ -27,9 +24,7 @@
</div> </div>
<div v-show="userInfo.id"> <div v-show="userInfo.id">
<div class="friend-detail"> <div class="friend-detail">
<head-image :size="200" <head-image :size="200" :name="userInfo.nickName" :url="userInfo.headImage"
:name="userInfo.nickName"
:url="userInfo.headImage"
@click.native="showFullImage()"></head-image> @click.native="showFullImage()"></head-image>
<div> <div>
<div class="info-item"> <div class="info-item">
@ -41,17 +36,20 @@
<el-descriptions-item label="性别">{{ userInfo.sex==0?"男":"女" }}</el-descriptions-item> <el-descriptions-item label="性别">{{ userInfo.sex==0?"男":"女" }}</el-descriptions-item>
<el-descriptions-item label="签名">{{ userInfo.signature }}</el-descriptions-item> <el-descriptions-item label="签名">{{ userInfo.signature }}</el-descriptions-item>
</el-descriptions> </el-descriptions>
</div> </div>
<div class="frient-btn-group"> <div class="frient-btn-group">
<el-button v-show="isFriend" icon="el-icon-chat-dot-round" type="primary" @click="onSendMessage(userInfo)">发送消息</el-button> <el-button v-show="isFriend" icon="el-icon-position" type="primary"
<el-button v-show="!isFriend" icon="el-icon-plus" type="primary" @click="onAddFriend(userInfo)">加为好友</el-button> @click="onSendMessage(userInfo)">发消息</el-button>
<el-button v-show="isFriend" icon="el-icon-delete" type="danger" @click="onDelItem(userInfo,activeIdx)">删除好友</el-button> <el-button v-show="!isFriend" icon="el-icon-plus" type="primary"
@click="onAddFriend(userInfo)">加为好友</el-button>
<el-button v-show="isFriend" icon="el-icon-delete" type="danger"
@click="onDelItem(userInfo,activeIdx)">删除好友</el-button>
</div> </div>
</div> </div>
</div> </div>
<el-divider content-position="center"></el-divider> <el-divider content-position="center"></el-divider>
</div> </div>
</el-container> </el-container>
</el-container> </el-container>
@ -106,7 +104,7 @@
}) })
}) })
}, },
onAddFriend(user){ onAddFriend(user) {
this.$http({ this.$http({
url: "/friend/add", url: "/friend/add",
method: "post", method: "post",
@ -116,12 +114,12 @@
}).then((data) => { }).then((data) => {
this.$message.success("添加成功,对方已成为您的好友"); this.$message.success("添加成功,对方已成为您的好友");
let friend = { let friend = {
id:user.id, id: user.id,
nickName: user.nickName, nickName: user.nickName,
headImage: user.headImage, headImage: user.headImage,
online: user.online online: user.online
} }
this.$store.commit("addFriend",friend); this.$store.commit("addFriend", friend);
}) })
}, },
onSendMessage(user) { onSendMessage(user) {
@ -172,14 +170,14 @@
friendStore() { friendStore() {
return this.$store.state.friendStore; return this.$store.state.friendStore;
}, },
isFriend(){ isFriend() {
return this.friendStore.friends.find((f)=>f.id==this.userInfo.id); return this.friendStore.friends.find((f) => f.id == this.userInfo.id);
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style lang="scss">
.friend-page { .friend-page {
.friend-list-box { .friend-list-box {
display: flex; display: flex;
@ -191,16 +189,29 @@
height: 50px; height: 50px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 5px; padding: 3px 8px;
background-color: white; background-color: #5870e6;
.friend-list-search { .el-input__inner {
flex: 1; border-radius: 10px !important;
background-color: #F8F8F8;
}
.add-btn {
padding: 5px !important;
margin: 5px;
font-size: 20px;
color: #587FF0;
border: #587FF0 1px solid;
background-color: #F0F8FF;
border-radius: 50%;
} }
} }
.friend-list-items { .friend-list-items {
flex: 1; flex: 1;
margin: 0 3px;
background: #F8F8F8;
} }
} }
@ -210,16 +221,14 @@
border: #dddddd solid 1px; border: #dddddd solid 1px;
.friend-header { .friend-header {
width: 100%; padding: 3px;
height: 50px; height: 50px;
padding: 5px;
line-height: 50px; line-height: 50px;
font-size: 20px; font-size: 20px;
text-align: left;
text-indent: 10px;
font-weight: 600; font-weight: 600;
background-color: white; text-align: center;
border: #dddddd solid 1px; color: #f8f8f8;
background-color: #5870e6;
} }
.friend-detail { .friend-detail {
@ -230,6 +239,7 @@
.info-item { .info-item {
margin-left: 20px; margin-left: 20px;
background-color: #ffffff; background-color: #ffffff;
border-radius: 10px ;
} }
.description { .description {

74
im-ui/src/view/Group.vue

@ -2,13 +2,11 @@
<el-container class="group-page"> <el-container class="group-page">
<el-aside width="260px" class="group-list-box"> <el-aside width="260px" class="group-list-box">
<div class="group-list-header"> <div class="group-list-header">
<div class="group-list-search"> <el-input class="search-text" placeholder="搜索" v-model="searchText">
<el-input width="200px" placeholder="搜索群聊" v-model="searchText"> <i class="el-icon-search el-input__icon" slot="prefix"> </i>
<el-button slot="append" icon="el-icon-search"></el-button> </el-input>
</el-input> <el-button plain class="add-btn" icon="el-icon-plus" title="创建群聊"
</div> @click="onCreateGroup()"></el-button>
<el-button plain icon="el-icon-plus" style="border: none; padding: 12px; font-size: 20px;color: black;"
title="创建群聊" @click="onCreateGroup()"></el-button>
</div> </div>
<el-scrollbar class="group-list-items"> <el-scrollbar class="group-list-items">
<div v-for="(group,index) in groupStore.groups" :key="index"> <div v-for="(group,index) in groupStore.groups" :key="index">
@ -26,17 +24,17 @@
<div v-show="activeGroup.id"> <div v-show="activeGroup.id">
<div class="group-info"> <div class="group-info">
<div> <div>
<file-upload v-show="isOwner" class="avatar-uploader" :action="imageAction" <file-upload v-show="isOwner" class="avatar-uploader" :action="imageAction"
:showLoading="true" :maxSize="maxSize" @success="onUploadSuccess" :showLoading="true" :maxSize="maxSize" @success="onUploadSuccess"
:fileTypes="['image/jpeg', 'image/png', 'image/jpg','image/webp']"> :fileTypes="['image/jpeg', 'image/png', 'image/jpg','image/webp']">
<img v-if="activeGroup.headImage" :src="activeGroup.headImage" class="avatar"> <img v-if="activeGroup.headImage" :src="activeGroup.headImage" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i> <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</file-upload> </file-upload>
<head-image v-show="!isOwner" class="avatar" :size="200" <head-image v-show="!isOwner" class="avatar" :size="200" :url="activeGroup.headImage"
:url="activeGroup.headImage"
:name="activeGroup.remark"> :name="activeGroup.remark">
</head-image> </head-image>
<el-button class="send-btn" icon="el-icon-chat-dot-round" type="primary" @click="onSendMessage()">发送消息</el-button> <el-button class="send-btn" icon="el-icon-position" type="primary"
@click="onSendMessage()">发消息</el-button>
</div> </div>
<el-form class="group-form" label-width="130px" :model="activeGroup" :rules="rules" <el-form class="group-form" label-width="130px" :model="activeGroup" :rules="rules"
ref="groupForm"> ref="groupForm">
@ -58,7 +56,7 @@
maxlength="1024" placeholder="群主未设置"></el-input> maxlength="1024" placeholder="群主未设置"></el-input>
</el-form-item> </el-form-item>
<div> <div>
<el-button type="success" @click="onSaveGroup()">提交</el-button> <el-button type="success" @click="onSaveGroup()">保存</el-button>
<el-button type="danger" v-show="!isOwner" @click="onQuit()">退出群聊</el-button> <el-button type="danger" v-show="!isOwner" @click="onQuit()">退出群聊</el-button>
<el-button type="danger" v-show="isOwner" @click="onDissolve()">解散群聊</el-button> <el-button type="danger" v-show="isOwner" @click="onDissolve()">解散群聊</el-button>
</div> </div>
@ -69,8 +67,7 @@
<div class="group-member-list"> <div class="group-member-list">
<div v-for="(member) in groupMembers" :key="member.id"> <div v-for="(member) in groupMembers" :key="member.id">
<group-member v-show="!member.quit" class="group-member" :member="member" <group-member v-show="!member.quit" class="group-member" :member="member"
:showDel="isOwner&&member.userId!=activeGroup.ownerId" :showDel="isOwner&&member.userId!=activeGroup.ownerId" @del="onKick"></group-member>
@del="onKick"></group-member>
</div> </div>
<div class="group-invite"> <div class="group-invite">
<div class="invite-member-btn" title="邀请好友进群聊" @click="onInviteMember()"> <div class="invite-member-btn" title="邀请好友进群聊" @click="onInviteMember()">
@ -159,7 +156,7 @@
this.showAddGroupMember = false; this.showAddGroupMember = false;
}, },
onUploadSuccess(data) { onUploadSuccess(data) {
this.activeGroup.headImage =data.originUrl; this.activeGroup.headImage = data.originUrl;
this.activeGroup.headImageThumb = data.thumbUrl; this.activeGroup.headImageThumb = data.thumbUrl;
}, },
onSaveGroup() { onSaveGroup() {
@ -249,9 +246,9 @@
this.groupMembers = members; this.groupMembers = members;
}) })
}, },
reset(){ reset() {
this.activeGroup={}; this.activeGroup = {};
this.groupMembers=[]; this.groupMembers = [];
} }
}, },
computed: { computed: {
@ -278,22 +275,34 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border: #dddddd solid 1px; border: #dddddd solid 1px;
background: white; background: #F8F8F8;
.group-list-header { .group-list-header {
height: 50px; height: 50px;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 5px; padding: 3px 8px;
background-color: white; background-color: #5870e6;
.group-list-search { .el-input__inner {
flex: 1; border-radius: 10px !important;
}
.add-btn {
padding: 5px !important;
margin: 5px;
font-size: 20px;
color: #587FF0;
border: #587FF0 1px solid;
background-color: #F0F8FF;
border-radius: 50%;
} }
} }
.group-list-items { .group-list-items {
flex: 1; flex: 1;
margin: 0 3px;
background: #F8F8F8;
} }
} }
@ -301,26 +310,25 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
border: #dddddd solid 1px; border: #dddddd solid 1px;
.group-header { .group-header {
width: 100%; padding: 3px;
height: 50px; height: 50px;
padding: 5px;
line-height: 50px; line-height: 50px;
font-size: 20px; font-size: 20px;
font-weight: 600; font-weight: 600;
text-align: left; text-align: center;
text-indent: 10px; color: #f8f8f8;
background-color: white; background-color: #5870e6;
border: #dddddd solid 1px;
} }
.group-container { .group-container {
padding: 20px; margin: 20px;
.group-info { .group-info {
display: flex; display: flex;
padding: 5px 20px; padding: 5px 20px;
.group-form { .group-form {
flex: 1; flex: 1;
padding-left: 40px; padding-left: 40px;

66
im-ui/src/view/Home.vue

@ -3,29 +3,29 @@
<el-aside width="80px" class="navi-bar"> <el-aside width="80px" class="navi-bar">
<div class="user-head-image"> <div class="user-head-image">
<head-image :name="$store.state.userStore.userInfo.nickName" <head-image :name="$store.state.userStore.userInfo.nickName"
:url="$store.state.userStore.userInfo.headImageThumb" :size="60" :url="$store.state.userStore.userInfo.headImageThumb" :size="50"
@click.native="showSettingDialog = true"> @click.native="showSettingDialog = true">
</head-image> </head-image>
</div> </div>
<el-menu background-color="#333333" text-color="#ddd" style="margin-top: 30px;"> <el-menu background-color="#19082f" style="margin-top: 25px;">
<el-menu-item title="聊天"> <el-menu-item title="聊天">
<router-link v-bind:to="'/home/chat'"> <router-link class="link" v-bind:to="'/home/chat'">
<span class="el-icon-chat-dot-round"></span> <span class="icon iconfont icon-chat"></span>
<div v-show="unreadCount > 0" class="unread-text">{{ unreadCount }}</div> <div v-show="unreadCount > 0" class="unread-text">{{ unreadCount }}</div>
</router-link> </router-link>
</el-menu-item> </el-menu-item>
<el-menu-item title="好友"> <el-menu-item title="好友">
<router-link v-bind:to="'/home/friend'"> <router-link class="link" v-bind:to="'/home/friend'">
<span class="el-icon-user"></span> <span class="icon iconfont icon-friend"></span>
</router-link> </router-link>
</el-menu-item> </el-menu-item>
<el-menu-item title="群聊"> <el-menu-item title="群聊">
<router-link v-bind:to="'/home/group'"> <router-link class="link" v-bind:to="'/home/group'">
<span class="icon iconfont icon-group_fill"></span> <span class="icon iconfont icon-group"></span>
</router-link> </router-link>
</el-menu-item> </el-menu-item>
<el-menu-item title="设置" @click="showSetting()"> <el-menu-item title="设置" @click="showSetting()">
<span class="el-icon-setting"></span> <span class="icon iconfont icon-setting"></span>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
<div class="exit-box" @click="onExit()" title="退出"> <div class="exit-box" @click="onExit()" title="退出">
@ -322,8 +322,8 @@
<style scoped lang="scss"> <style scoped lang="scss">
.navi-bar { .navi-bar {
background: #333333; background: #19082f;
padding: 10px; padding: 15px;
padding-top: 50px; padding-top: 50px;
.el-menu { .el-menu {
@ -331,21 +331,25 @@
flex: 1; flex: 1;
.el-menu-item { .el-menu-item {
margin: 25px 0; margin: 20px 0;
background-color: #19082f !important;
.router-link-exact-active span { padding: 0 !important;
color: white !important; text-align: center;
} .link {
text-decoration: none;
&.router-link-active .icon {
span { color: #d5894c;
font-size: 24px !important;
color: #aaaaaa;
&:hover {
color: white !important;
} }
&:hover .icon{
color: white;
}
}
.icon {
font-size: 26px !important;
color: #ddd;
} }
.unread-text { .unread-text {
@ -365,30 +369,28 @@
} }
} }
.exit-box { .exit-box {
position: absolute; position: absolute;
width: 60px; width: 60px;
bottom: 40px; bottom: 40px;
color: #aaaaaa; color: #ccc;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
.icon { .icon {
font-size: 28px; font-size: 28px;
} }
&:hover { &:hover {
color: white !important; color: white;
} }
} }
} }
.content-box { .content-box {
padding: 0; padding: 0;
background-color: #E9EEF3; background-color: #eee;
color: #333; color: black;
text-align: center; text-align: center;
} }
</style> </style>

9
im-ui/src/view/Login.vue

@ -30,6 +30,13 @@
<li>uniapp移动端支持发送语音消息</li> <li>uniapp移动端支持发送语音消息</li>
</ul> </ul>
</div> </div>
<div>
<h3>最近更新(2024-04-27)</h3>
<ul>
<li>uniapp端加载离线消息慢以及卡顿问题优化</li>
<li>web端样式风格调整</li>
</ul>
</div>
<div> <div>
<h3>如果本项目对您有帮助,请在gitee上帮忙点个star</h3> <h3>如果本项目对您有帮助,请在gitee上帮忙点个star</h3>
</div> </div>
@ -178,7 +185,7 @@
.login-view { .login-view {
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgb(232, 242, 255); background: #E8F2FF;
background-size: cover; background-size: cover;
box-sizing: border-box; box-sizing: border-box;

Loading…
Cancel
Save