Browse Source

前端代码格式化(使用vscode默认格式)

master
xsx 1 year ago
parent
commit
cc627ec45a
  1. 41
      im-uniapp/App.vue
  2. 6
      im-uniapp/common/date.js
  3. 52
      im-uniapp/common/enums.js
  4. 24
      im-uniapp/common/messageType.js
  5. 8
      im-uniapp/common/recorder-h5.js
  6. 4
      im-uniapp/common/request.js
  7. 10
      im-uniapp/common/wssocket.js
  8. 11
      im-uniapp/components/bar/arrow-bar.vue
  9. 8
      im-uniapp/components/bar/bar-group.vue
  10. 12
      im-uniapp/components/bar/btn-bar.vue
  11. 14
      im-uniapp/components/bar/switch-bar.vue
  12. 35
      im-uniapp/components/chat-at-box/chat-at-box.vue
  13. 17
      im-uniapp/components/chat-group-readed/chat-group-readed.vue
  14. 23
      im-uniapp/components/chat-item/chat-item.vue
  15. 49
      im-uniapp/components/chat-message-item/chat-message-item.vue
  16. 20
      im-uniapp/components/chat-record/chat-record.vue
  17. 11
      im-uniapp/components/file-upload/file-upload.vue
  18. 17
      im-uniapp/components/friend-item/friend-item.vue
  19. 19
      im-uniapp/components/group-item/group-item.vue
  20. 17
      im-uniapp/components/group-member-selector/group-member-selector.vue
  21. 17
      im-uniapp/components/group-rtc-join/group-rtc-join.vue
  22. 24
      im-uniapp/components/head-image/head-image.vue
  23. 21
      im-uniapp/components/image-upload/image-upload.vue
  24. 20
      im-uniapp/components/loading/loading.vue
  25. 9
      im-uniapp/components/nav-bar/nav-bar.vue
  26. 36
      im-uniapp/components/pop-menu/pop-menu.vue
  27. 5
      im-uniapp/main.js
  28. 167
      im-uniapp/manifest.json
  29. 57
      im-uniapp/pages.json
  30. 46
      im-uniapp/pages/chat/chat-box.vue
  31. 10
      im-uniapp/pages/chat/chat-group-video.vue
  32. 27
      im-uniapp/pages/chat/chat-private-video.vue
  33. 27
      im-uniapp/pages/chat/chat.vue
  34. 18
      im-uniapp/pages/common/user-info.vue
  35. 25
      im-uniapp/pages/friend/friend-add.vue
  36. 46
      im-uniapp/pages/friend/friend.vue
  37. 23
      im-uniapp/pages/group/group-edit.vue
  38. 45
      im-uniapp/pages/group/group-info.vue
  39. 31
      im-uniapp/pages/group/group-invite.vue
  40. 30
      im-uniapp/pages/group/group-member.vue
  41. 13
      im-uniapp/pages/group/group.vue
  42. 8
      im-uniapp/pages/login/login.vue
  43. 34
      im-uniapp/pages/mine/mine-edit.vue
  44. 17
      im-uniapp/pages/mine/mine-password.vue
  45. 26
      im-uniapp/pages/mine/mine.vue
  46. 10
      im-uniapp/pages/register/register.vue
  47. 26
      im-uniapp/store/chatStore.js
  48. 2
      im-uniapp/store/userStore.js
  49. 2
      im-uniapp/vite.config.js
  50. 1
      im-web/src/view/Login.vue

41
im-uniapp/App.vue

@ -1,12 +1,12 @@
<script> <script>
import App from './App' import App from './App'
import http from './common/request'; import http from './common/request';
import * as msgType from './common/messageType'; import * as msgType from './common/messageType';
import * as enums from './common/enums'; import * as enums from './common/enums';
import * as wsApi from './common/wssocket'; import * as wsApi from './common/wssocket';
import UNI_APP from '@/.env.js' import UNI_APP from '@/.env.js'
export default { export default {
data() { data() {
return { return {
isExit: false, // 退 isExit: false, // 退
@ -79,7 +79,7 @@
return Promise.all(promises); return Promise.all(promises);
}) })
}, },
unloadStore(){ unloadStore() {
this.friendStore.clear(); this.friendStore.clear();
this.groupStore.clear(); this.groupStore.clear();
this.chatStore.clear(); this.chatStore.clear();
@ -378,21 +378,22 @@
// #endif // #endif
}) })
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss">
@import "@/uni_modules/uview-plus/index.scss"; @import "@/uni_modules/uview-plus/index.scss";
@import "@/im.scss"; @import "@/im.scss";
@import url('./static/icon/iconfont.css'); @import url('./static/icon/iconfont.css');
// #ifdef H5 // #ifdef H5
uni-page-head { uni-page-head {
display: none; // h5 display: none; // h5
} }
// #endif
.tab-page { // #endif
.tab-page {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -409,9 +410,9 @@
background-color: $im-bg; background-color: $im-bg;
font-size: $im-font-size; font-size: $im-font-size;
font-family: $font-family; font-family: $font-family;
} }
.page { .page {
position: relative; position: relative;
// #ifdef H5 // #ifdef H5
height: calc(100vh - $im-nav-bar-height); // app height: calc(100vh - $im-nav-bar-height); // app
@ -425,5 +426,5 @@
background-color: $im-bg; background-color: $im-bg;
font-size: $im-font-size; font-size: $im-font-size;
font-family: $font-family; font-family: $font-family;
} }
</style> </style>

6
im-uniapp/common/date.js

@ -20,8 +20,8 @@ let toTimeText = (timeStamp, simple) => {
} else { } else {
//不属于今年 //不属于今年
timeText = formatDateTime(dateTime); timeText = formatDateTime(dateTime);
if(simple){ if (simple) {
timeText = timeText.substr(2,8); timeText = timeText.substr(2, 8);
} }
} }
return timeText; return timeText;
@ -58,7 +58,7 @@ let formatDateTime = (date) => {
} }
export{ export {
toTimeText, toTimeText,
isYestday, isYestday,
isYear, isYear,

52
im-uniapp/common/enums.js

@ -2,18 +2,18 @@
const MESSAGE_TYPE = { const MESSAGE_TYPE = {
TEXT: 0, TEXT: 0,
IMAGE: 1, IMAGE: 1,
FILE:2, FILE: 2,
AUDIO:3, AUDIO: 3,
VIDEO:4, VIDEO: 4,
RECALL:10, RECALL: 10,
READED:11, READED: 11,
RECEIPT:12, RECEIPT: 12,
TIP_TIME:20, TIP_TIME: 20,
TIP_TEXT:21, TIP_TEXT: 21,
LOADING:30, LOADING: 30,
ACT_RT_VOICE:40, ACT_RT_VOICE: 40,
ACT_RT_VIDEO:41, ACT_RT_VIDEO: 41,
USER_BANNED:50, USER_BANNED: 50,
RTC_CALL_VOICE: 100, RTC_CALL_VOICE: 100,
RTC_CALL_VIDEO: 101, RTC_CALL_VIDEO: 101,
RTC_ACCEPT: 102, RTC_ACCEPT: 102,
@ -22,18 +22,18 @@ const MESSAGE_TYPE = {
RTC_FAILED: 105, RTC_FAILED: 105,
RTC_HANDUP: 106, RTC_HANDUP: 106,
RTC_CANDIDATE: 107, RTC_CANDIDATE: 107,
RTC_GROUP_SETUP:200, RTC_GROUP_SETUP: 200,
RTC_GROUP_ACCEPT:201, RTC_GROUP_ACCEPT: 201,
RTC_GROUP_REJECT:202, RTC_GROUP_REJECT: 202,
RTC_GROUP_FAILED:203, RTC_GROUP_FAILED: 203,
RTC_GROUP_CANCEL:204, RTC_GROUP_CANCEL: 204,
RTC_GROUP_QUIT:205, RTC_GROUP_QUIT: 205,
RTC_GROUP_INVITE:206, RTC_GROUP_INVITE: 206,
RTC_GROUP_JOIN:207, RTC_GROUP_JOIN: 207,
RTC_GROUP_OFFER:208, RTC_GROUP_OFFER: 208,
RTC_GROUP_ANSWER:209, RTC_GROUP_ANSWER: 209,
RTC_GROUP_CANDIDATE:210, RTC_GROUP_CANDIDATE: 210,
RTC_GROUP_DEVICE:211 RTC_GROUP_DEVICE: 211
} }
const USER_STATE = { const USER_STATE = {
@ -50,8 +50,8 @@ const TERMINAL_TYPE = {
const MESSAGE_STATUS = { const MESSAGE_STATUS = {
UNSEND: 0, UNSEND: 0,
SENDED: 1, SENDED: 1,
RECALL:2, RECALL: 2,
READED:3 READED: 3
} }
export { export {

24
im-uniapp/common/messageType.js

@ -1,32 +1,32 @@
// 是否普通消息 // 是否普通消息
let isNormal = function(type){ let isNormal = function (type) {
return type>=0 && type < 10; return type >= 0 && type < 10;
} }
// 是否状态消息 // 是否状态消息
let isStatus = function(type){ let isStatus = function (type) {
return type>=10 && type < 20; return type >= 10 && type < 20;
} }
// 是否提示消息 // 是否提示消息
let isTip = function(type){ let isTip = function (type) {
return type>=20 && type < 30; return type >= 20 && type < 30;
} }
// 操作交互类消息 // 操作交互类消息
let isAction = function(type){ let isAction = function (type) {
return type>=40 && type < 50; return type >= 40 && type < 50;
} }
// 单人通话信令 // 单人通话信令
let isRtcPrivate = function(type){ let isRtcPrivate = function (type) {
return type>=100 && type < 200; return type >= 100 && type < 200;
} }
// 多人通话信令 // 多人通话信令
let isRtcGroup = function(type){ let isRtcGroup = function (type) {
return type>=200 && type < 300; return type >= 200 && type < 300;
} }

8
im-uniapp/common/recorder-h5.js

@ -3,7 +3,7 @@ import UNI_APP from '@/.env.js';
let rc = null; let rc = null;
let start = () => { let start = () => {
if(rc != null){ if (rc != null) {
close(); close();
} }
rc = new Recorder(); rc = new Recorder();
@ -22,7 +22,7 @@ let close = () => {
let upload = () => { let upload = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const wavBlob = rc.getWAVBlob(); const wavBlob = rc.getWAVBlob();
const newbolb = new Blob([wavBlob], { type: 'audio/wav'}) const newbolb = new Blob([wavBlob], { type: 'audio/wav' })
const name = new Date().getDate() + '.wav'; const name = new Date().getDate() + '.wav';
const file = new File([newbolb], name) const file = new File([newbolb], name)
uni.uploadFile({ uni.uploadFile({
@ -34,10 +34,10 @@ let upload = () => {
name: 'file', name: 'file',
success: (res) => { success: (res) => {
let r = JSON.parse(res.data); let r = JSON.parse(res.data);
if(r.code != 200){ if (r.code != 200) {
console.log(res) console.log(res)
reject(r.message); reject(r.message);
}else { } else {
const data = { const data = {
duration: parseInt(rc.duration), duration: parseInt(rc.duration),
url: r.data url: r.data

4
im-uniapp/common/request.js

@ -11,7 +11,7 @@ const request = (options) => {
if (loginInfo) { if (loginInfo) {
header.accessToken = loginInfo.accessToken; header.accessToken = loginInfo.accessToken;
} }
return new Promise(function(resolve, reject) { return new Promise(function (resolve, reject) {
uni.request({ uni.request({
url: UNI_APP.BASE_URL + options.url, url: UNI_APP.BASE_URL + options.url,
method: options.method || 'GET', method: options.method || 'GET',
@ -72,7 +72,7 @@ const request = (options) => {
const reqRefreshToken = (loginInfo) => { const reqRefreshToken = (loginInfo) => {
return new Promise(function(resolve, reject) { return new Promise(function (resolve, reject) {
uni.request({ uni.request({
method: 'PUT', method: 'PUT',
url: UNI_APP.BASE_URL + '/refreshToken', url: UNI_APP.BASE_URL + '/refreshToken',

10
im-uniapp/common/wssocket.js

@ -55,7 +55,7 @@ let init = () => {
console.log(e) console.log(e)
isConnect = false; isConnect = false;
// APP 应用切出超过一定时间(约1分钟)会触发报错,此处回调给应用进行重连 // APP 应用切出超过一定时间(约1分钟)会触发报错,此处回调给应用进行重连
closeCallBack && closeCallBack({code: 1006}); closeCallBack && closeCallBack({ code: 1006 });
}) })
}; };
@ -92,7 +92,7 @@ let reconnect = (wsurl, accessToken) => {
let timeDiff = new Date().getTime() - lastConnectTime.getTime() let timeDiff = new Date().getTime() - lastConnectTime.getTime()
let delay = timeDiff < 10000 ? 10000 - timeDiff : 0; let delay = timeDiff < 10000 ? 10000 - timeDiff : 0;
rec && clearTimeout(rec); rec && clearTimeout(rec);
rec = setTimeout(function() { rec = setTimeout(function () {
connect(wsurl, accessToken); connect(wsurl, accessToken);
}, delay); }, delay);
}; };
@ -119,7 +119,7 @@ let close = (code) => {
var heartCheck = { var heartCheck = {
timeout: 10000, //每段时间发送一次心跳包 这里设置为30s timeout: 10000, //每段时间发送一次心跳包 这里设置为30s
timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象) timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)
start: function() { start: function () {
if (isConnect) { if (isConnect) {
console.log('发送WebSocket心跳') console.log('发送WebSocket心跳')
let heartBeat = { let heartBeat = {
@ -134,9 +134,9 @@ var heartCheck = {
}) })
} }
}, },
reset: function() { reset: function () {
clearTimeout(this.timeoutObj); clearTimeout(this.timeoutObj);
this.timeoutObj = setTimeout(function() { this.timeoutObj = setTimeout(function () {
heartCheck.start(); heartCheck.start();
}, this.timeout); }, this.timeout);
} }

11
im-uniapp/components/bar/arrow-bar.vue

@ -1,12 +1,12 @@
<template> <template>
<view class="arrow-bar"> <view class="arrow-bar">
<text class="title">{{title}}</text> <text class="title">{{ title }}</text>
<uni-icons class="arrow" type="right" size="16"></uni-icons> <uni-icons class="arrow" type="right" size="16"></uni-icons>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "arrow-bar", name: "arrow-bar",
props: { props: {
title: { title: {
@ -14,11 +14,11 @@
required: true required: true
} }
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.arrow-bar { .arrow-bar {
width: 100%; width: 100%;
height: 90rpx; height: 90rpx;
font-size: 30rpx; font-size: 30rpx;
@ -27,6 +27,7 @@
background-color: white; background-color: white;
line-height: 90rpx; line-height: 90rpx;
display: flex; display: flex;
.title { .title {
flex: 1; flex: 1;
margin-left: 40rpx; margin-left: 40rpx;
@ -35,5 +36,5 @@
.arrow { .arrow {
margin-right: 40rpx; margin-right: 40rpx;
} }
} }
</style> </style>

8
im-uniapp/components/bar/bar-group.vue

@ -5,13 +5,13 @@
</template> </template>
<script> <script>
export default{ export default {
name: "bar-group" name: "bar-group"
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.bar-group{ .bar-group {
margin: 20rpx 0; margin: 20rpx 0;
} }
</style> </style>

12
im-uniapp/components/bar/btn-bar.vue

@ -1,12 +1,12 @@
<template> <template>
<view class="btn-bar" :style="style"> <view class="btn-bar" :style="style">
<text v-if="icon" class="icon iconfont" :class="icon"></text> <text v-if="icon" class="icon iconfont" :class="icon"></text>
<text class="title">{{title}}</text> <text class="title">{{ title }}</text>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "btn-bar", name: "btn-bar",
props: { props: {
title: { title: {
@ -40,11 +40,11 @@
return `color: ${color};` return `color: ${color};`
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.btn-bar { .btn-bar {
width: 100%; width: 100%;
height: 100rpx; height: 100rpx;
margin-top: 5rpx; margin-top: 5rpx;
@ -53,14 +53,16 @@
text-align: center; text-align: center;
display: flex; display: flex;
justify-content: center; justify-content: center;
.icon { .icon {
font-size: 40rpx; font-size: 40rpx;
font-weight: 600; font-weight: 600;
margin-right: 10rpx; margin-right: 10rpx;
} }
.title { .title {
font-size: 32rpx; font-size: 32rpx;
font-weight: 600; font-weight: 600;
} }
} }
</style> </style>

14
im-uniapp/components/bar/switch-bar.vue

@ -1,12 +1,12 @@
<template> <template>
<view class="switch-bar"> <view class="switch-bar">
<text class="title">{{title}}</text> <text class="title">{{ title }}</text>
<switch class="switch" :checked="checked" color="#18bc37" @change="onChange"></switch> <switch class="switch" :checked="checked" color="#18bc37" @change="onChange"></switch>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "switch-bar", name: "switch-bar",
props: { props: {
title: { title: {
@ -26,20 +26,20 @@
methods: { methods: {
onChange(e) { onChange(e) {
this.value = true; this.value = true;
setTimeout(()=>{ setTimeout(() => {
this.value = false; this.value = false;
},100) }, 100)
//this.value = false; //this.value = false;
this.$emit('change', e); this.$emit('change', e);
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.switch-bar { .switch-bar {
width: 100%; width: 100%;
height: 100rpx; height: 100rpx;
font-size: 34rpx; font-size: 34rpx;
@ -57,5 +57,5 @@
.switch { .switch {
margin-right: 40rpx; margin-right: 40rpx;
} }
} }
</style> </style>

35
im-uniapp/components/chat-at-box/chat-at-box.vue

@ -4,12 +4,12 @@
<view class="chat-at-top"> <view class="chat-at-top">
<view class="chat-at-tip"> 选择要提醒的人</view> <view class="chat-at-tip"> 选择要提醒的人</view>
<button class="chat-at-btn" type="warn" size="mini" @click="onClean()">清空 </button> <button class="chat-at-btn" type="warn" size="mini" @click="onClean()">清空 </button>
<button class="chat-at-btn" type="primary" size="mini" @click="onOk()">确定({{atUserIds.length}}) <button class="chat-at-btn" type="primary" size="mini" @click="onOk()">确定({{ atUserIds.length }})
</button> </button>
</view> </view>
<scroll-view v-show="atUserIds.length>0" scroll-x="true" scroll-left="120"> <scroll-view v-show="atUserIds.length > 0" scroll-x="true" scroll-left="120">
<view class="at-user-items"> <view class="at-user-items">
<view v-for="m in showMembers" v-show="m.checked" class="at-user-item"> <view v-for="m in showMembers" v-show="m.checked" class="at-user-item" :key="m.userId">
<head-image :name="m.showNickName" :url="m.headImage" size="mini"></head-image> <head-image :name="m.showNickName" :url="m.headImage" size="mini"></head-image>
</view> </view>
</view> </view>
@ -19,15 +19,14 @@
</view> </view>
<view class="member-items"> <view class="member-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="m in showMembers" v-show="m.showNickName.includes(searchText)" <view v-for="m in showMembers" v-show="m.showNickName.includes(searchText)" :key="m.userId">
:key="m.userId"> <view class="member-item" :class="{ checked: m.checked }" @click="onSwitchChecked(m)">
<view class="member-item" :class="{checked: m.checked}" @click="onSwitchChecked(m)">
<head-image :name="m.showNickName" :online="m.online" :url="m.headImage" <head-image :name="m.showNickName" :online="m.online" :url="m.headImage"
size="small"></head-image> size="small"></head-image>
<view class="member-name">{{ m.showNickName}}</view> <view class="member-name">{{ m.showNickName }}</view>
<!-- <view class="member-checked">--> <!-- <view class="member-checked">-->
<!-- <radio :checked="m.checked" @click.stop="onSwitchChecked(m)" />--> <!-- <radio :checked="m.checked" @click.stop="onSwitchChecked(m)" />-->
<!-- </view>--> <!-- </view>-->
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
@ -37,7 +36,7 @@
</template> </template>
<script> <script>
export default { export default {
name: "chat-at-box", name: "chat-at-box",
props: { props: {
ownerId: { ownerId: {
@ -50,21 +49,21 @@
data() { data() {
return { return {
searchText: "", searchText: "",
showMembers:[] showMembers: []
}; };
}, },
methods: { methods: {
init(atUserIds) { init(atUserIds) {
this.showMembers = []; this.showMembers = [];
let userId = this.userStore.userInfo.id; let userId = this.userStore.userInfo.id;
if(this.ownerId == userId){ if (this.ownerId == userId) {
this.showMembers.push({ this.showMembers.push({
userId:-1, userId: -1,
showNickName: "全体成员" showNickName: "全体成员"
}) })
} }
this.members.forEach((m) => { this.members.forEach((m) => {
if(!m.quit && m.userId != userId){ if (!m.quit && m.userId != userId) {
m.checked = atUserIds.indexOf(m.userId) >= 0; m.checked = atUserIds.indexOf(m.userId) >= 0;
this.showMembers.push(m); this.showMembers.push(m);
} }
@ -101,12 +100,12 @@
return ids; return ids;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-at-box { .chat-at-box {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -175,5 +174,5 @@
height: 800rpx; height: 800rpx;
} }
} }
} }
</style> </style>

17
im-uniapp/components/chat-group-readed/chat-group-readed.vue

@ -2,7 +2,8 @@
<uni-popup ref="popup" type="bottom"> <uni-popup ref="popup" type="bottom">
<view class="chat-group-readed"> <view class="chat-group-readed">
<view class="uni-padding-wrap uni-common-mt"> <view class="uni-padding-wrap uni-common-mt">
<uni-segmented-control :current="current" :values="items" style-type="button" @clickItem="onClickItem"/> <uni-segmented-control :current="current" :values="items" style-type="button"
@clickItem="onClickItem" />
</view> </view>
<view class="content"> <view class="content">
<view v-if="current === 0"> <view v-if="current === 0">
@ -11,7 +12,7 @@
<view class="member-item"> <view class="member-item">
<head-image :name="m.aliasName" :online="m.online" :url="m.headImage" <head-image :name="m.aliasName" :online="m.online" :url="m.headImage"
:size="90"></head-image> :size="90"></head-image>
<view class="member-name">{{ m.aliasName}}</view> <view class="member-name">{{ m.aliasName }}</view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
@ -22,7 +23,7 @@
<view class="member-item"> <view class="member-item">
<head-image :name="m.aliasName" :online="m.online" :url="m.headImage" <head-image :name="m.aliasName" :online="m.online" :url="m.headImage"
:size="90"></head-image> :size="90"></head-image>
<view class="member-name">{{ m.aliasName}}</view> <view class="member-name">{{ m.aliasName }}</view>
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
@ -33,7 +34,7 @@
</template> </template>
<script> <script>
export default { export default {
name: "chat-group-readed", name: "chat-group-readed",
data() { data() {
return { return {
@ -86,15 +87,15 @@
}) })
}) })
}, },
onClickItem(e){ onClickItem(e) {
this.current = e.currentIndex; this.current = e.currentIndex;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-group-readed { .chat-group-readed {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -127,5 +128,5 @@
} }
} }
</style> </style>

23
im-uniapp/components/chat-item/chat-item.vue

@ -1,5 +1,5 @@
<template> <template>
<view class="chat-item" :class="active?'active':''"> <view class="chat-item" :class="active ? 'active' : ''">
<!--rich-text中的表情包会屏蔽事件所以这里用一个遮罩层捕获点击事件 --> <!--rich-text中的表情包会屏蔽事件所以这里用一个遮罩层捕获点击事件 -->
<view class="mask" @tap="showChatBox()"></view> <view class="mask" @tap="showChatBox()"></view>
<view class="left"> <view class="left">
@ -8,23 +8,23 @@
<view class="chat-right"> <view class="chat-right">
<view class="chat-name"> <view class="chat-name">
<view class="chat-name-text"> <view class="chat-name-text">
<view>{{chat.showName}}</view> <view>{{ chat.showName }}</view>
<uni-tag v-if="chat.type=='GROUP'" circle text="群" size="small" type="primary"></uni-tag> <uni-tag v-if="chat.type == 'GROUP'" circle text="群" size="small" type="primary"></uni-tag>
</view> </view>
<view class="chat-time">{{$date.toTimeText(chat.lastSendTime,true)}}</view> <view class="chat-time">{{ $date.toTimeText(chat.lastSendTime, true) }}</view>
</view> </view>
<view class="chat-content"> <view class="chat-content">
<view class="chat-at-text">{{atText}}</view> <view class="chat-at-text">{{ atText }}</view>
<view class="chat-send-name" v-if="isShowSendName">{{chat.sendNickName+':&nbsp;'}}</view> <view class="chat-send-name" v-if="isShowSendName">{{ chat.sendNickName + ':&nbsp;' }}</view>
<rich-text class="chat-content-text" :nodes="$emo.transform(chat.lastContent)"></rich-text> <rich-text class="chat-content-text" :nodes="$emo.transform(chat.lastContent)"></rich-text>
<uni-badge v-if="chat.unreadCount>0" :max-num="99" :text="chat.unreadCount" /> <uni-badge v-if="chat.unreadCount > 0" :max-num="99" :text="chat.unreadCount" />
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "chatItem", name: "chatItem",
data() { data() {
return {} return {}
@ -71,11 +71,11 @@
return ""; return "";
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.chat-item { .chat-item {
height: 96rpx; height: 96rpx;
display: flex; display: flex;
margin-bottom: 2rpx; margin-bottom: 2rpx;
@ -155,6 +155,7 @@
font-size: $im-font-size-smaller; font-size: $im-font-size-smaller;
color: $im-text-color-lighter; color: $im-text-color-lighter;
padding-top: 8rpx; padding-top: 8rpx;
.chat-at-text { .chat-at-text {
color: $im-color-danger; color: $im-color-danger;
} }
@ -177,5 +178,5 @@
} }
} }
} }
</style> </style>

49
im-uniapp/components/chat-message-item/chat-message-item.vue

@ -1,26 +1,26 @@
<template> <template>
<view class="chat-msg-item"> <view class="chat-msg-item">
<view class="chat-msg-tip" <view class="chat-msg-tip"
v-if="msgInfo.type==$enums.MESSAGE_TYPE.RECALL||msgInfo.type == $enums.MESSAGE_TYPE.TIP_TEXT"> v-if="msgInfo.type == $enums.MESSAGE_TYPE.RECALL || msgInfo.type == $enums.MESSAGE_TYPE.TIP_TEXT">
{{msgInfo.content}} {{ msgInfo.content }}
</view> </view>
<view class="chat-msg-tip" v-if="msgInfo.type==$enums.MESSAGE_TYPE.TIP_TIME"> <view class="chat-msg-tip" v-if="msgInfo.type == $enums.MESSAGE_TYPE.TIP_TIME">
{{$date.toTimeText(msgInfo.sendTime)}} {{ $date.toTimeText(msgInfo.sendTime) }}
</view> </view>
<view class="chat-msg-normal" v-if="isNormal" :class="{'chat-msg-mine':msgInfo.selfSend}"> <view class="chat-msg-normal" v-if="isNormal" :class="{ 'chat-msg-mine': msgInfo.selfSend }">
<head-image class="avatar" @longpress.prevent="$emit('longPressHead')" :id="msgInfo.sendId" :url="headImage" <head-image class="avatar" @longpress.prevent="$emit('longPressHead')" :id="msgInfo.sendId" :url="headImage"
:name="showName" size="small"></head-image> :name="showName" size="small"></head-image>
<view class="chat-msg-content"> <view class="chat-msg-content">
<view v-if="msgInfo.groupId && !msgInfo.selfSend" class="chat-msg-top"> <view v-if="msgInfo.groupId && !msgInfo.selfSend" class="chat-msg-top">
<text>{{showName}}</text> <text>{{ showName }}</text>
</view> </view>
<view class="chat-msg-bottom"> <view class="chat-msg-bottom">
<view v-if="msgInfo.type==$enums.MESSAGE_TYPE.TEXT"> <view v-if="msgInfo.type == $enums.MESSAGE_TYPE.TEXT">
<pop-menu :items="menuItems" @select="onSelectMenu"> <pop-menu :items="menuItems" @select="onSelectMenu">
<rich-text class="chat-msg-text" :nodes="$emo.transform(msgInfo.content)"></rich-text> <rich-text class="chat-msg-text" :nodes="$emo.transform(msgInfo.content)"></rich-text>
</pop-menu> </pop-menu>
</view> </view>
<view class="chat-msg-image" v-if="msgInfo.type==$enums.MESSAGE_TYPE.IMAGE"> <view class="chat-msg-image" v-if="msgInfo.type == $enums.MESSAGE_TYPE.IMAGE">
<pop-menu :items="menuItems" @select="onSelectMenu"> <pop-menu :items="menuItems" @select="onSelectMenu">
<view class="img-load-box"> <view class="img-load-box">
<image class="send-image" mode="widthFix" :src="JSON.parse(msgInfo.content).thumbUrl" <image class="send-image" mode="widthFix" :src="JSON.parse(msgInfo.content).thumbUrl"
@ -32,13 +32,13 @@
<text title="发送失败" v-if="loadFail" @click="onSendFail" <text title="发送失败" v-if="loadFail" @click="onSendFail"
class="send-fail iconfont icon-warning-circle-fill"></text> class="send-fail iconfont icon-warning-circle-fill"></text>
</view> </view>
<view class="chat-msg-file" v-if="msgInfo.type==$enums.MESSAGE_TYPE.FILE"> <view class="chat-msg-file" v-if="msgInfo.type == $enums.MESSAGE_TYPE.FILE">
<pop-menu :items="menuItems" @select="onSelectMenu"> <pop-menu :items="menuItems" @select="onSelectMenu">
<view class="chat-file-box"> <view class="chat-file-box">
<view class="chat-file-info"> <view class="chat-file-info">
<uni-link class="chat-file-name" :text="data.name" showUnderLine="true" <uni-link class="chat-file-name" :text="data.name" showUnderLine="true"
color="#007BFF" :href="data.url"></uni-link> color="#007BFF" :href="data.url"></uni-link>
<view class="chat-file-size">{{fileSize}}</view> <view class="chat-file-size">{{ fileSize }}</view>
</view> </view>
<view class="chat-file-icon iconfont icon-file"></view> <view class="chat-file-icon iconfont icon-file"></view>
<loading v-if="loading"></loading> <loading v-if="loading"></loading>
@ -47,32 +47,32 @@
<text title="发送失败" v-if="loadFail" @click="onSendFail" <text title="发送失败" v-if="loadFail" @click="onSendFail"
class="send-fail iconfont icon-warning-circle-fill"></text> class="send-fail iconfont icon-warning-circle-fill"></text>
</view> </view>
<pop-menu v-if="msgInfo.type==$enums.MESSAGE_TYPE.AUDIO" :items="menuItems" @select="onSelectMenu"> <pop-menu v-if="msgInfo.type == $enums.MESSAGE_TYPE.AUDIO" :items="menuItems" @select="onSelectMenu">
<view class="chat-msg-audio chat-msg-text" @click="onPlayAudio()"> <view class="chat-msg-audio chat-msg-text" @click="onPlayAudio()">
<text class="iconfont icon-voice-play"></text> <text class="iconfont icon-voice-play"></text>
<text class="chat-audio-text">{{JSON.parse(msgInfo.content).duration+'"'}}</text> <text class="chat-audio-text">{{ JSON.parse(msgInfo.content).duration + '"' }}</text>
<text v-if="audioPlayState=='PAUSE'" class="iconfont icon-play"></text> <text v-if="audioPlayState == 'PAUSE'" class="iconfont icon-play"></text>
<text v-if="audioPlayState=='PLAYING'" class="iconfont icon-pause"></text> <text v-if="audioPlayState == 'PLAYING'" class="iconfont icon-pause"></text>
</view> </view>
</pop-menu> </pop-menu>
<pop-menu v-if="isAction" :items="menuItems" @select="onSelectMenu"> <pop-menu v-if="isAction" :items="menuItems" @select="onSelectMenu">
<view class="chat-realtime chat-msg-text" @click="$emit('call')"> <view class="chat-realtime chat-msg-text" @click="$emit('call')">
<text v-if="msgInfo.type==$enums.MESSAGE_TYPE.ACT_RT_VOICE" <text v-if="msgInfo.type == $enums.MESSAGE_TYPE.ACT_RT_VOICE"
class="iconfont icon-chat-voice"></text> class="iconfont icon-chat-voice"></text>
<text v-if="msgInfo.type==$enums.MESSAGE_TYPE.ACT_RT_VIDEO" <text v-if="msgInfo.type == $enums.MESSAGE_TYPE.ACT_RT_VIDEO"
class="iconfont icon-chat-video"></text> class="iconfont icon-chat-video"></text>
<text>{{msgInfo.content}}</text> <text>{{ msgInfo.content }}</text>
</view> </view>
</pop-menu> </pop-menu>
<view class="chat-msg-status" v-if="!isAction"> <view class="chat-msg-status" v-if="!isAction">
<text class="chat-readed" v-show="msgInfo.selfSend && !msgInfo.groupId <text class="chat-readed" v-show="msgInfo.selfSend && !msgInfo.groupId
&& msgInfo.status==$enums.MESSAGE_STATUS.READED">已读</text> && msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</text>
<text class="chat-unread" v-show="msgInfo.selfSend && !msgInfo.groupId <text class="chat-unread" v-show="msgInfo.selfSend && !msgInfo.groupId
&& msgInfo.status!=$enums.MESSAGE_STATUS.READED">未读</text> && msgInfo.status != $enums.MESSAGE_STATUS.READED">未读</text>
</view> </view>
<view class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox"> <view class="chat-receipt" v-show="msgInfo.receipt" @click="onShowReadedBox">
<text v-if="msgInfo.receiptOk" class="tool-icon iconfont icon-ok"></text> <text v-if="msgInfo.receiptOk" class="tool-icon iconfont icon-ok"></text>
<text v-else>{{msgInfo.readedCount}}人已读</text> <text v-else>{{ msgInfo.readedCount }}人已读</text>
</view> </view>
</view> </view>
</view> </view>
@ -83,7 +83,7 @@
</template> </template>
<script> <script>
export default { export default {
name: "chat-message-item", name: "chat-message-item",
props: { props: {
headImage: { headImage: {
@ -220,11 +220,11 @@
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.chat-msg-item { .chat-msg-item {
padding: 2rpx 20rpx; padding: 2rpx 20rpx;
.chat-msg-tip { .chat-msg-tip {
@ -393,6 +393,7 @@
line-height: $im-font-size-smaller-extra; line-height: $im-font-size-smaller-extra;
font-size: $im-font-size-smaller-extra; font-size: $im-font-size-smaller-extra;
padding-top: 2rpx; padding-top: 2rpx;
.chat-readed { .chat-readed {
display: block; display: block;
padding-top: 2rpx; padding-top: 2rpx;
@ -482,5 +483,5 @@
} }
} }
} }
</style> </style>

20
im-uniapp/components/chat-record/chat-record.vue

@ -1,8 +1,8 @@
<template> <template>
<view class="chat-record"> <view class="chat-record">
<view class="chat-record-bar" :class="{recording: recording }" id="chat-record-bar" @click.stop="" <view class="chat-record-bar" :class="{ recording: recording }" id="chat-record-bar" @click.stop=""
@touchstart.prevent="onStartRecord" @touchmove.prevent="onTouchMove" @touchend.prevent="onEndRecord"> @touchstart.prevent="onStartRecord" @touchmove.prevent="onTouchMove" @touchend.prevent="onEndRecord">
{{recording?'正在录音':'长按 说话'}}</view> {{ recording ? '正在录音' : '长按 说话' }}</view>
<view v-if="recording" class="chat-record-window" :style="recordWindowStyle"> <view v-if="recording" class="chat-record-window" :style="recordWindowStyle">
<view class="rc-wave"> <view class="rc-wave">
<text class="note" style="--d: 0"></text> <text class="note" style="--d: 0"></text>
@ -13,18 +13,18 @@
<text class="note" style="--d: 5"></text> <text class="note" style="--d: 5"></text>
<text class="note" style="--d: 6"></text> <text class="note" style="--d: 6"></text>
</view> </view>
<view class="rc-tip">{{recordTip}}</view> <view class="rc-tip">{{ recordTip }}</view>
<view class="cancel-btn" @click="onCancel"> <view class="cancel-btn" @click="onCancel">
<uni-icons :class="moveToCancel?'red':'black'" type="clear" :size="moveToCancel?45:40"></uni-icons> <uni-icons :class="moveToCancel ? 'red' : 'black'" type="clear" :size="moveToCancel ? 45 : 40"></uni-icons>
</view> </view>
<view class="opt-tip" :class="moveToCancel?'red':'black'">{{moveToCancel? '松手取消':'松手发送,上划取消'}}</view> <view class="opt-tip" :class="moveToCancel ? 'red' : 'black'">{{ moveToCancel ? '松手取消' : '松手发送,上划取消' }}</view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "chat-record", name: "chat-record",
data() { data() {
return { return {
@ -132,17 +132,17 @@
}, },
recordTip() { recordTip() {
if (this.druation > 50) { if (this.druation > 50) {
return `${60-this.druation}s后将停止录音`; return `${60 - this.druation}s后将停止录音`;
} }
return `录音时长:${this.druation}s`; return `录音时长:${this.druation}s`;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-record { .chat-record {
.rc-wave { .rc-wave {
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
@ -234,5 +234,5 @@
} }
} }
} }
</style> </style>

11
im-uniapp/components/file-upload/file-upload.vue

@ -8,9 +8,9 @@
</template> </template>
<script> <script>
import UNI_APP from '@/.env.js'; import UNI_APP from '@/.env.js';
export default { export default {
name: "file-upload", name: "file-upload",
data() { data() {
return { return {
@ -74,7 +74,7 @@
return; return;
} }
files.forEach((file, name) => { files.forEach((file, name) => {
if(!this.fileMap.has(file.path)){ if (!this.fileMap.has(file.path)) {
this.onBefore && this.onBefore(file) this.onBefore && this.onBefore(file)
this.fileMap.set(file.path, file); this.fileMap.set(file.path, file);
} }
@ -110,8 +110,7 @@
} }
} }
} }
</script> </script>
<style> <style></style>
</style>

17
im-uniapp/components/friend-item/friend-item.vue

@ -2,19 +2,17 @@
<view class="friend-item" @click="showFriendInfo()"> <view class="friend-item" @click="showFriendInfo()">
<head-image :name="friend.nickName" :online="friend.online" :url="friend.headImage" size="small"></head-image> <head-image :name="friend.nickName" :online="friend.online" :url="friend.headImage" size="small"></head-image>
<view class="friend-info"> <view class="friend-info">
<view class="friend-name">{{ friend.nickName}}</view> <view class="friend-name">{{ friend.nickName }}</view>
<view class="friend-online"> <view class="friend-online">
<image v-show="friend.onlineWeb" class="online" src="/static/image/online_web.png" <image v-show="friend.onlineWeb" class="online" src="/static/image/online_web.png" title="电脑设备在线" />
title="电脑设备在线" /> <image v-show="friend.onlineApp" class="online" src="/static/image/online_app.png" title="移动设备在线" />
<image v-show="friend.onlineApp" class="online" src="/static/image/online_app.png"
title="移动设备在线" />
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "frined-item", name: "frined-item",
data() { data() {
return {} return {}
@ -31,11 +29,11 @@
type: Object type: Object
} }
} }
} }
</script> </script>
<style scope lang="scss"> <style scope lang="scss">
.friend-item { .friend-item {
height: 90rpx; height: 90rpx;
display: flex; display: flex;
margin-bottom: 1rpx; margin-bottom: 1rpx;
@ -65,6 +63,7 @@
.friend-online { .friend-online {
margin-top: 4rpx; margin-top: 4rpx;
.online { .online {
padding-right: 4rpx; padding-right: 4rpx;
width: 24rpx; width: 24rpx;
@ -72,5 +71,5 @@
} }
} }
} }
} }
</style> </style>

19
im-uniapp/components/group-item/group-item.vue

@ -1,23 +1,22 @@
<template> <template>
<view class="group-item" @click="showGroupInfo()"> <view class="group-item" @click="showGroupInfo()">
<head-image :name="group.showGroupName" <head-image :name="group.showGroupName" :url="group.headImage" size="small"></head-image>
:url="group.headImage" size="small"></head-image>
<view class="group-name"> <view class="group-name">
<view>{{ group.showGroupName}}</view> <view>{{ group.showGroupName }}</view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "group-item", name: "group-item",
data() { data() {
return {} return {}
}, },
methods:{ methods: {
showGroupInfo(){ showGroupInfo() {
uni.navigateTo({ uni.navigateTo({
url:"/pages/group/group-info?id="+this.group.id url: "/pages/group/group-info?id=" + this.group.id
}) })
}, },
}, },
@ -26,11 +25,11 @@
type: Object type: Object
} }
} }
} }
</script> </script>
<style scope lang="scss"> <style scope lang="scss">
.group-item { .group-item {
height: 90rpx; height: 90rpx;
display: flex; display: flex;
margin-bottom: 2rpx; margin-bottom: 2rpx;
@ -55,5 +54,5 @@
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
} }
} }
</style> </style>

17
im-uniapp/components/group-member-selector/group-member-selector.vue

@ -4,12 +4,12 @@
<view class="top-bar"> <view class="top-bar">
<view class="top-tip">选择成员</view> <view class="top-tip">选择成员</view>
<button class="top-btn" type="warn" size="mini" @click="onClean()">清空 </button> <button class="top-btn" type="warn" size="mini" @click="onClean()">清空 </button>
<button class="top-btn" type="primary" size="mini" @click="onOk()">确定({{checkedIds.length}}) <button class="top-btn" type="primary" size="mini" @click="onOk()">确定({{ checkedIds.length }})
</button> </button>
</view> </view>
<scroll-view v-show="checkedIds.length>0" scroll-x="true" scroll-left="120"> <scroll-view v-show="checkedIds.length > 0" scroll-x="true" scroll-left="120">
<view class="checked-users"> <view class="checked-users">
<view v-for="m in members" v-show="m.checked" class="user-item"> <view v-for="m in members" v-show="m.checked" class="user-item" :key="m.userId">
<head-image :name="m.showNickName" :url="m.headImage" :size="60"></head-image> <head-image :name="m.showNickName" :url="m.headImage" :size="60"></head-image>
</view> </view>
</view> </view>
@ -23,7 +23,7 @@
<view class="member-item" @click="onSwitchChecked(m)"> <view class="member-item" @click="onSwitchChecked(m)">
<head-image :name="m.showNickName" :online="m.online" :url="m.headImage" <head-image :name="m.showNickName" :online="m.online" :url="m.headImage"
:size="90"></head-image> :size="90"></head-image>
<view class="member-name">{{ m.showNickName}}</view> <view class="member-name">{{ m.showNickName }}</view>
<view class="member-checked"> <view class="member-checked">
<radio :checked="m.checked" :disabled="m.locked" @click.stop="onSwitchChecked(m)" /> <radio :checked="m.checked" :disabled="m.locked" @click.stop="onSwitchChecked(m)" />
</view> </view>
@ -37,7 +37,7 @@
<script> <script>
export default { export default {
name: "chat-group-member-choose", name: "chat-group-member-choose",
props: { props: {
members: { members: {
@ -102,12 +102,12 @@
return ids; return ids;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-group-member-choose { .chat-group-member-choose {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -135,6 +135,7 @@
align-items: center; align-items: center;
height: 90rpx; height: 90rpx;
padding: 0 30rpx; padding: 0 30rpx;
.user-item { .user-item {
padding: 3rpx; padding: 3rpx;
} }
@ -169,5 +170,5 @@
height: 800rpx; height: 800rpx;
} }
} }
} }
</style> </style>

17
im-uniapp/components/group-rtc-join/group-rtc-join.vue

@ -1,17 +1,16 @@
<template> <template>
<uni-popup ref="popup" type="center"> <uni-popup ref="popup" type="center">
<uni-popup-dialog mode="base" :duration="2000" title="是否加入通话?" confirmText="加入" <uni-popup-dialog mode="base" :duration="2000" title="是否加入通话?" confirmText="加入" @confirm="onOk">
@confirm="onOk">
<div class="group-rtc-join"> <div class="group-rtc-join">
<div class="host-info"> <div class="host-info">
<div>发起人</div> <div>发起人</div>
<head-image :name="rtcInfo.host.nickName" :url="rtcInfo.host.headImage" :size="80"></head-image> <head-image :name="rtcInfo.host.nickName" :url="rtcInfo.host.headImage" :size="80"></head-image>
</div> </div>
<div class="user-info"> <div class="user-info">
<div>{{rtcInfo.userInfos.length+'人正在通话中'}}</div> <div>{{ rtcInfo.userInfos.length + '人正在通话中' }}</div>
<scroll-view scroll-x="true" scroll-left="120"> <scroll-view scroll-x="true" scroll-left="120">
<view class="user-list"> <view class="user-list">
<view v-for="user in rtcInfo.userInfos" class="user-item"> <view v-for="user in rtcInfo.userInfos" class="user-item" :key="user.id">
<head-image :name="user.nickName" :url="user.headImage" :size="80"></head-image> <head-image :name="user.nickName" :url="user.headImage" :size="80"></head-image>
</view> </view>
</view> </view>
@ -23,7 +22,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
rtcInfo: {} rtcInfo: {}
@ -43,7 +42,7 @@
let users = this.rtcInfo.userInfos; let users = this.rtcInfo.userInfos;
let mine = this.userStore.userInfo; let mine = this.userStore.userInfo;
// //
if(!users.find((user)=>user.id==mine.id)){ if (!users.find((user) => user.id == mine.id)) {
users.push({ users.push({
id: mine.id, id: mine.id,
nickName: mine.nickName, nickName: mine.nickName,
@ -59,11 +58,11 @@
}) })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.group-rtc-join { .group-rtc-join {
width: 100%; width: 100%;
.host-info { .host-info {
@ -85,5 +84,5 @@
padding: 3rpx; padding: 3rpx;
} }
} }
} }
</style> </style>

24
im-uniapp/components/head-image/head-image.vue

@ -1,9 +1,9 @@
<template> <template>
<view class="head-image" @click="showUserInfo($event)" :title="name"> <view class="head-image" @click="showUserInfo($event)" :title="name">
<image class="avatar-image" v-if="url" :src="url" <image class="avatar-image" v-if="url" :src="url" :style="avatarImageStyle" lazy-load="true"
:style="avatarImageStyle" lazy-load="true" mode="aspectFill"/> mode="aspectFill" />
<view class="avatar-text" v-if="!url" :style="avatarTextStyle"> <view class="avatar-text" v-if="!url" :style="avatarTextStyle">
{{name?.substring(0,1).toUpperCase()}} {{ name?.substring(0, 1).toUpperCase() }}
</view> </view>
<view v-if="online" class="online" title="用户当前在线"> <view v-if="online" class="online" title="用户当前在线">
</view> </view>
@ -11,7 +11,7 @@
</template> </template>
<script> <script>
export default { export default {
name: "head-image", name: "head-image",
data() { data() {
return { return {
@ -43,16 +43,16 @@
showUserInfo(e) { showUserInfo(e) {
if (this.id && this.id > 0) { if (this.id && this.id > 0) {
uni.navigateTo({ uni.navigateTo({
url: "/pages/common/user-info?id="+this.id url: "/pages/common/user-info?id=" + this.id
}) })
} }
} }
}, },
computed: { computed: {
_size(){ _size() {
if(typeof this.size === 'number'){ if (typeof this.size === 'number') {
return this.size; return this.size;
} else if(typeof this.size === 'string'){ } else if (typeof this.size === 'string') {
return { return {
'default': 96, 'default': 96,
'small': 84, 'small': 84,
@ -72,7 +72,7 @@
return `width: ${this._size}rpx; return `width: ${this._size}rpx;
height:${this._size}rpx; height:${this._size}rpx;
background-color:${this.name ? this.textColor : '#fff'}; background-color:${this.name ? this.textColor : '#fff'};
font-size:${this._size*0.5}rpx; font-size:${this._size * 0.5}rpx;
` `
}, },
textColor() { textColor() {
@ -83,11 +83,11 @@
return this.colors[hash % this.colors.length]; return this.colors[hash % this.colors.length];
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.head-image { .head-image {
position: relative; position: relative;
cursor: pointer; cursor: pointer;
@ -116,5 +116,5 @@
border-radius: 50%; border-radius: 50%;
border: 6rpx solid white; border: 6rpx solid white;
} }
} }
</style> </style>

21
im-uniapp/components/image-upload/image-upload.vue

@ -5,9 +5,9 @@
</template> </template>
<script> <script>
import UNI_APP from '@/.env.js' import UNI_APP from '@/.env.js'
export default { export default {
name: "image-upload", name: "image-upload",
data() { data() {
return { return {
@ -17,15 +17,15 @@
} }
}, },
props: { props: {
maxCount:{ maxCount: {
type: Number, type: Number,
default: 1 default: 1
}, },
maxSize: { maxSize: {
type: Number, type: Number,
default: 5*1024*1024 default: 5 * 1024 * 1024
}, },
sourceType:{ sourceType: {
type: String, type: String,
default: 'album' default: 'album'
}, },
@ -50,7 +50,7 @@
sizeType: ['original'], //original compressed sizeType: ['original'], //original compressed
success: (res) => { success: (res) => {
res.tempFiles.forEach((file) => { res.tempFiles.forEach((file) => {
console.log("文件:",file) console.log("文件:", file)
if (!this.onBefore || this.onBefore(file)) { if (!this.onBefore || this.onBefore(file)) {
// //
this.uploadImage(file); this.uploadImage(file);
@ -69,13 +69,13 @@
name: 'file', name: 'file',
success: (res) => { success: (res) => {
let data = JSON.parse(res.data); let data = JSON.parse(res.data);
if(data.code != 200){ if (data.code != 200) {
uni.showToast({ uni.showToast({
icon: "none", icon: "none",
title: data.message, title: data.message,
}) })
this.onError && this.onError(file, data); this.onError && this.onError(file, data);
}else{ } else {
this.onSuccess && this.onSuccess(file, data); this.onSuccess && this.onSuccess(file, data);
} }
}, },
@ -86,8 +86,7 @@
}) })
} }
} }
} }
</script> </script>
<style> <style></style>
</style>

20
im-uniapp/components/loading/loading.vue

@ -6,10 +6,8 @@
</template> </template>
<script> <script>
import {
computed export default {
} from "vue"
export default {
data() { data() {
return {} return {}
}, },
@ -31,11 +29,11 @@
return this.mask ? "background: rgba(0, 0, 0, 0.3);" : ""; return this.mask ? "background: rgba(0, 0, 0, 0.3);" : "";
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.loading-box { .loading-box {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -45,14 +43,14 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.rotate { .rotate {
animation: rotate 2s ease-in-out infinite; animation: rotate 2s ease-in-out infinite;
} }
@keyframes rotate { @keyframes rotate {
from { from {
transform: rotate(0deg) transform: rotate(0deg)
} }
@ -60,5 +58,5 @@
to { to {
transform: rotate(360deg) transform: rotate(360deg)
} }
} }
</style> </style>

9
im-uniapp/components/nav-bar/nav-bar.vue

@ -11,9 +11,11 @@
<slot></slot> <slot></slot>
</view> </view>
<view class="btn"> <view class="btn">
<uni-icons class="btn-item" v-if="search" type="search" :size="iconFontSize" @click="$emit('search')"></uni-icons> <uni-icons class="btn-item" v-if="search" type="search" :size="iconFontSize"
@click="$emit('search')"></uni-icons>
<uni-icons class="btn-item" v-if="add" type="plusempty" :size="iconFontSize" @click="$emit('add')"></uni-icons> <uni-icons class="btn-item" v-if="add" type="plusempty" :size="iconFontSize" @click="$emit('add')"></uni-icons>
<uni-icons class="btn-item" v-if="more" type="more-filled" :size="iconFontSize" @click="$emit('more')"></uni-icons> <uni-icons class="btn-item" v-if="more" type="more-filled" :size="iconFontSize"
@click="$emit('more')"></uni-icons>
</view> </view>
</view> </view>
</view> </view>
@ -85,8 +87,7 @@ export default {
box-sizing: border-box; box-sizing: border-box;
height: $im-nav-bar-height; height: $im-nav-bar-height;
.title { .title {}
}
.back { .back {
position: absolute; position: absolute;

36
im-uniapp/components/pop-menu/pop-menu.vue

@ -6,21 +6,20 @@
<view v-if="isShowMenu" class="pop-menu" @touchstart="onClose()" @contextmenu.prevent=""></view> <view v-if="isShowMenu" class="pop-menu" @touchstart="onClose()" @contextmenu.prevent=""></view>
<view v-if="isShowMenu" class="menu" :style="menuStyle"> <view v-if="isShowMenu" class="menu" :style="menuStyle">
<view class="menu-item" v-for="(item) in items" :key="item.key" @click.prevent="onSelectMenu(item)"> <view class="menu-item" v-for="(item) in items" :key="item.key" @click.prevent="onSelectMenu(item)">
<!-- <uni-icons class="menu-icon" :type="item.icon" :style="itemStyle(item)" size="20"></uni-icons>--> <text :style="itemStyle(item)"> {{ item.name }}</text>
<text :style="itemStyle(item)"> {{item.name}}</text>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
name: "pop-menu", name: "pop-menu",
data() { data() {
return { return {
isShowMenu : false, isShowMenu: false,
isTouchMove: false, isTouchMove: false,
style : "" style: ""
} }
}, },
props: { props: {
@ -29,8 +28,8 @@
} }
}, },
methods: { methods: {
onLongPress(e){ onLongPress(e) {
if(this.isTouchMove){ if (this.isTouchMove) {
// //
return; return;
} }
@ -40,12 +39,12 @@
let style = ""; let style = "";
/* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */ /* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */
if (touches.clientY > (res.windowHeight / 2)) { if (touches.clientY > (res.windowHeight / 2)) {
style = `bottom:${res.windowHeight-touches.clientY}px;`; style = `bottom:${res.windowHeight - touches.clientY}px;`;
} else { } else {
style = `top:${touches.clientY}px;`; style = `top:${touches.clientY}px;`;
} }
if (touches.clientX > (res.windowWidth / 2)) { if (touches.clientX > (res.windowWidth / 2)) {
style += `right:${res.windowWidth-touches.clientX}px;`; style += `right:${res.windowWidth - touches.clientX}px;`;
} else { } else {
style += `left:${touches.clientX}px;`; style += `left:${touches.clientX}px;`;
} }
@ -57,11 +56,11 @@
} }
}) })
}, },
onTouchMove(){ onTouchMove() {
this.onClose(); this.onClose();
this.isTouchMove = true; this.isTouchMove = true;
}, },
onTouchEnd(){ onTouchEnd() {
this.isTouchMove = false; this.isTouchMove = false;
}, },
onSelectMenu(item) { onSelectMenu(item) {
@ -71,18 +70,18 @@
onClose() { onClose() {
this.isShowMenu = false; this.isShowMenu = false;
}, },
itemStyle(item){ itemStyle(item) {
if(item.color){ if (item.color) {
return `color:${item.color};` return `color:${item.color};`
} }
// return `color:#4f76e6;`; // return `color:#4f76e6;`;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.pop-menu { .pop-menu {
position: fixed; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
@ -91,15 +90,16 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: 999; z-index: 999;
} }
.menu { .menu {
position: fixed; position: fixed;
border-radius: 4px; border-radius: 4px;
overflow: hidden; overflow: hidden;
background-color: #fff; background-color: #fff;
z-index: 1000; z-index: 1000;
box-shadow: $im-box-shadow-dark; box-shadow: $im-box-shadow-dark;
.menu-item { .menu-item {
height: 28px; height: 28px;
min-width: 120rpx; min-width: 120rpx;
@ -117,5 +117,5 @@
margin-right: 10rpx; margin-right: 10rpx;
} }
} }
} }
</style> </style>

5
im-uniapp/main.js

@ -27,9 +27,6 @@ import * as recorder from './common/recorder-h5';
// #ifndef H5 // #ifndef H5
import * as recorder from './common/recorder-app'; import * as recorder from './common/recorder-app';
// #endif // #endif
export function createApp() { export function createApp() {
const app = createSSRApp(App) const app = createSSRApp(App)
app.use(uviewPlus); app.use(uviewPlus);
@ -46,7 +43,7 @@ export function createApp() {
app.config.globalProperties.$date = date; app.config.globalProperties.$date = date;
app.config.globalProperties.$rc = recorder; app.config.globalProperties.$rc = recorder;
// 初始化时再挂载store对象 // 初始化时再挂载store对象
app.config.globalProperties.$mountStore = ()=>{ app.config.globalProperties.$mountStore = () => {
app.config.globalProperties.chatStore = useChatStore(); app.config.globalProperties.chatStore = useChatStore();
app.config.globalProperties.friendStore = useFriendStore(); app.config.globalProperties.friendStore = useFriendStore();
app.config.globalProperties.groupStore = useGroupStore(); app.config.globalProperties.groupStore = useGroupStore();

167
im-uniapp/manifest.json

@ -1,32 +1,32 @@
{ {
"name" : "盒子IM", "name": "盒子IM",
"appid" : "__UNI__69DD57A", "appid": "__UNI__69DD57A",
"description" : "", "description": "",
"versionName" : "3.1.0", "versionName": "3.1.0",
"versionCode" : 3100, "versionCode": 3100,
"transformPx" : false, "transformPx": false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus": {
"usingComponents" : true, "usingComponents": true,
"nvueStyleCompiler" : "uni-app", "nvueStyleCompiler": "uni-app",
"compilerVersion" : 3, "compilerVersion": 3,
"splashscreen" : { "splashscreen": {
"alwaysShowBeforeRender" : true, "alwaysShowBeforeRender": true,
"waiting" : true, "waiting": true,
"autoclose" : true, "autoclose": true,
"delay" : 0 "delay": 0
}, },
/* */ /* */
"modules" : { "modules": {
"Camera" : {}, "Camera": {},
"Record" : {}, "Record": {},
"Bluetooth" : {} "Bluetooth": {}
}, },
/* */ /* */
"distribute" : { "distribute": {
/* android */ /* android */
"android" : { "android": {
"permissions" : [ "permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
@ -45,87 +45,90 @@
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />", "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\" />",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />" "<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />"
], ],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ], "abiFilters": [
"minSdkVersion" : 21 "armeabi-v7a",
"arm64-v8a",
"x86"
],
"minSdkVersion": 21
}, },
/* ios */ /* ios */
"ios" : { "ios": {
"dSYMs" : false, "dSYMs": false,
"privacyDescription" : { "privacyDescription": {
"NSMicrophoneUsageDescription" : "", "NSMicrophoneUsageDescription": "",
"NSCameraUsageDescription" : "" "NSCameraUsageDescription": ""
}, },
"idfa" : false "idfa": false
}, },
/* SDK */ /* SDK */
"sdkConfigs" : { "sdkConfigs": {
"ad" : {}, "ad": {},
"speech" : {} "speech": {}
}, },
"icons" : { "icons": {
"android" : { "android": {
"xhdpi" : "unpackage/res/icons/96x96.png", "xhdpi": "unpackage/res/icons/96x96.png",
"hdpi" : "unpackage/res/icons/72x72.png", "hdpi": "unpackage/res/icons/72x72.png",
"xxhdpi" : "unpackage/res/icons/144x144.png", "xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png" "xxxhdpi": "unpackage/res/icons/192x192.png"
}, },
"ios" : { "ios": {
"appstore" : "unpackage/res/icons/1024x1024.png", "appstore": "unpackage/res/icons/1024x1024.png",
"ipad" : { "ipad": {
"app" : "unpackage/res/icons/76x76.png", "app": "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png", "app@2x": "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png", "notification": "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png", "notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png", "proapp@2x": "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png", "settings": "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png", "settings@2x": "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png", "spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png" "spotlight@2x": "unpackage/res/icons/80x80.png"
}, },
"iphone" : { "iphone": {
"app@2x" : "unpackage/res/icons/120x120.png", "app@2x": "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png", "app@3x": "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png", "notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png", "notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png", "settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png", "settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png", "spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png" "spotlight@3x": "unpackage/res/icons/120x120.png"
} }
} }
} }
} }
}, },
/* */ /* */
"quickapp" : {}, "quickapp": {},
/* */ /* */
"mp-weixin" : { "mp-weixin": {
"appid" : "wxda94f40bfad0262c", "appid": "wxda94f40bfad0262c",
"libVersion" : "latest", "libVersion": "latest",
"setting" : { "setting": {
"urlCheck" : false "urlCheck": false
}, },
"usingComponents" : true "usingComponents": true
}, },
"mp-alipay" : { "mp-alipay": {
"usingComponents" : true "usingComponents": true
}, },
"mp-baidu" : { "mp-baidu": {
"usingComponents" : true "usingComponents": true
}, },
"mp-toutiao" : { "mp-toutiao": {
"usingComponents" : true "usingComponents": true
}, },
"uniStatistics" : { "uniStatistics": {
"enable" : false "enable": false
}, },
"vueVersion" : "3", "vueVersion": "3",
"h5" : { "h5": {
"title" : "盒子IM", "title": "盒子IM",
"router" : { "router": {
"base" : "/h5/" "base": "/h5/"
} }
} }
} }
/* ios *//* SDK */ /* ios */ /* SDK */

57
im-uniapp/pages.json

@ -7,39 +7,56 @@
"^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue" "^u-([^-].*)": "@/uni_modules/uview-plus/components/u-$1/u-$1.vue"
} }
}, },
"pages": [{ "pages": [
{
"path": "pages/login/login" "path": "pages/login/login"
}, { },
"path" : "pages/register/register" {
},{ "path": "pages/register/register"
},
{
"path": "pages/chat/chat" "path": "pages/chat/chat"
}, { },
{
"path": "pages/friend/friend" "path": "pages/friend/friend"
}, { },
{
"path": "pages/group/group" "path": "pages/group/group"
}, { },
{
"path": "pages/mine/mine" "path": "pages/mine/mine"
}, { },
{
"path": "pages/common/user-info" "path": "pages/common/user-info"
}, { },
{
"path": "pages/chat/chat-box" "path": "pages/chat/chat-box"
},{ },
{
"path": "pages/chat/chat-private-video" "path": "pages/chat/chat-private-video"
},{ },
{
"path": "pages/chat/chat-group-video" "path": "pages/chat/chat-group-video"
}, { },
{
"path": "pages/friend/friend-add" "path": "pages/friend/friend-add"
}, { },
{
"path": "pages/group/group-info" "path": "pages/group/group-info"
}, { },
{
"path": "pages/group/group-edit" "path": "pages/group/group-edit"
}, { },
{
"path": "pages/group/group-invite" "path": "pages/group/group-invite"
}, { },
{
"path": "pages/group/group-member" "path": "pages/group/group-member"
}, { },
{
"path": "pages/mine/mine-edit" "path": "pages/mine/mine-edit"
},{ },
{
"path": "pages/mine/mine-password" "path": "pages/mine/mine-password"
} }
], ],
@ -53,12 +70,12 @@
"selectedColor": "#587ff0", "selectedColor": "#587ff0",
"borderStyle": "black", "borderStyle": "black",
"backgroundColor": "#ffffff", "backgroundColor": "#ffffff",
"list": [{ "list": [
{
"pagePath": "pages/chat/chat", "pagePath": "pages/chat/chat",
"iconPath": "static/tarbar/chat.png", "iconPath": "static/tarbar/chat.png",
"selectedIconPath": "static/tarbar/chat_active.png", "selectedIconPath": "static/tarbar/chat_active.png",
"text": "消息" "text": "消息"
}, },
{ {
"pagePath": "pages/friend/friend", "pagePath": "pages/friend/friend",

46
im-uniapp/pages/chat/chat-box.vue

@ -1,21 +1,21 @@
<template> <template>
<view class="page chat-box"> <view class="page chat-box">
<nav-bar back more @more="onShowMore">{{title}}</nav-bar> <nav-bar back more @more="onShowMore">{{ title }}</nav-bar>
<view class="chat-msg" @click="switchChatTabBox('none',true)"> <view class="chat-msg" @click="switchChatTabBox('none', true)">
<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop" <scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop"
:scroll-into-view="'chat-item-'+scrollMsgIdx"> :scroll-into-view="'chat-item-' + scrollMsgIdx">
<view v-if="chat" v-for="(msgInfo,idx) in chat.messages" :key="idx"> <view v-if="chat" v-for="(msgInfo, idx) in chat.messages" :key="idx">
<chat-message-item v-if="idx>=showMinIdx" :headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)" <chat-message-item v-if="idx >= showMinIdx" :headImage="headImage(msgInfo)" @call="onRtCall(msgInfo)"
:showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage" :showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage"
@delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile" @delete="onDeleteMessage" @longPressHead="onLongPressHead(msgInfo)" @download="onDownloadFile"
:id="'chat-item-'+idx" :msgInfo="msgInfo" :groupMembers="groupMembers"> :id="'chat-item-' + idx" :msgInfo="msgInfo" :groupMembers="groupMembers">
</chat-message-item> </chat-message-item>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<view v-if="atUserIds.length>0" class="chat-at-bar" @click="openAtBox()"> <view v-if="atUserIds.length > 0" class="chat-at-bar" @click="openAtBox()">
<view class="iconfont icon-at">:&nbsp;</view> <view class="iconfont icon-at">:&nbsp;</view>
<scroll-view v-if="atUserIds.length>0" class="chat-at-scroll-box" scroll-x="true" scroll-left="120"> <scroll-view v-if="atUserIds.length > 0" class="chat-at-scroll-box" scroll-x="true" scroll-left="120">
<view class="chat-at-items"> <view class="chat-at-items">
<view v-for="m in atUserItems" class="chat-at-item"> <view v-for="m in atUserItems" class="chat-at-item">
<head-image :name="m.showNickName" :url="m.headImage" size="minier"></head-image> <head-image :name="m.showNickName" :url="m.headImage" size="minier"></head-image>
@ -29,19 +29,20 @@
<chat-record v-if="showRecord" class="chat-record" @send="onSendRecord"></chat-record> <chat-record v-if="showRecord" class="chat-record" @send="onSendRecord"></chat-record>
<view v-else class="send-text"> <view v-else class="send-text">
<textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false" <textarea class="send-text-area" v-model="sendText" auto-height :show-confirm-bar="false"
:placeholder="isReceipt?'[回执消息]':''" :adjust-position="false" @confirm="sendTextMessage()" :placeholder="isReceipt ? '[回执消息]' : ''" :adjust-position="false" @confirm="sendTextMessage()"
@keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send" confirm-hold @keyboardheightchange="onKeyboardheightchange" @input="onTextInput" confirm-type="send" confirm-hold
:hold-keyboard="true"></textarea> :hold-keyboard="true"></textarea>
</view> </view>
<view v-if="chat && chat.type=='GROUP'" class="iconfont icon-at" @click="openAtBox()"></view> <view v-if="chat && chat.type == 'GROUP'" class="iconfont icon-at" @click="openAtBox()"></view>
<view class="iconfont icon-icon_emoji" @click="onShowEmoChatTab()"></view> <view class="iconfont icon-icon_emoji" @click="onShowEmoChatTab()"></view>
<view v-if="sendText==''" class="iconfont icon-add" @click="onShowToolsChatTab()"> <view v-if="sendText == ''" class="iconfont icon-add" @click="onShowToolsChatTab()">
</view> </view>
<button v-if="sendText!=''||atUserIds.length>0" class="btn-send" type="primary" <button v-if="sendText != '' || atUserIds.length > 0" class="btn-send" type="primary"
@touchend.prevent="sendTextMessage()" size="mini">发送</button> @touchend.prevent="sendTextMessage()" size="mini">发送</button>
</view> </view>
<view class="chat-tab-bar" v-show="chatTabBox!='none' || (showKeyBoard && !isH5) " :style="{height:`${keyboardHeight}px`}"> <view class="chat-tab-bar" v-show="chatTabBox != 'none' || (showKeyBoard && !isH5)"
:style="{ height: `${keyboardHeight}px` }">
<view v-if="chatTabBox == 'tools'" class="chat-tools"> <view v-if="chatTabBox == 'tools'" class="chat-tools">
<view class="chat-tools-item"> <view class="chat-tools-item">
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore" <image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore"
@ -71,7 +72,7 @@
<view class="tool-name">语音消息</view> <view class="tool-name">语音消息</view>
</view> </view>
<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="switchReceipt()"> <view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="switchReceipt()">
<view class="tool-icon iconfont icon-receipt" :class="isReceipt?'active':''"></view> <view class="tool-icon iconfont icon-receipt" :class="isReceipt ? 'active' : ''"></view>
<view class="tool-name">回执消息</view> <view class="tool-name">回执消息</view>
</view> </view>
<!-- #ifndef MP-WEIXIN --> <!-- #ifndef MP-WEIXIN -->
@ -90,7 +91,7 @@
</view> </view>
<!-- #endif --> <!-- #endif -->
</view> </view>
<scroll-view v-if="chatTabBox==='emo'" class="chat-emotion" scroll-y="true"> <scroll-view v-if="chatTabBox === 'emo'" class="chat-emotion" scroll-y="true">
<view class="emotion-item-list"> <view class="emotion-item-list">
<image class="emotion-item" :title="emoText" :src="$emo.textToPath(emoText)" <image class="emotion-item" :title="emoText" :src="$emo.textToPath(emoText)"
v-for="(emoText, i) in $emo.emoTextList" :key="i" @click="selectEmoji(emoText)" mode="aspectFit" v-for="(emoText, i) in $emo.emoTextList" :key="i" @click="selectEmoji(emoText)" mode="aspectFit"
@ -112,9 +113,9 @@
</template> </template>
<script> <script>
import UNI_APP from '@/.env.js'; import UNI_APP from '@/.env.js';
export default { export default {
data() { data() {
return { return {
chat: {}, chat: {},
@ -707,7 +708,7 @@
} }
}, },
watch: { watch: {
messageSize: function(newSize, oldSize) { messageSize: function (newSize, oldSize) {
// //
if (newSize > oldSize) { if (newSize > oldSize) {
let pages = getCurrentPages(); let pages = getCurrentPages();
@ -759,11 +760,11 @@
this.needScrollToBottom = false; this.needScrollToBottom = false;
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-box { .chat-box {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -831,7 +832,8 @@
} }
$icon-color: rgba(0,0,0, 0.88); $icon-color: rgba(0, 0, 0, 0.88);
.send-bar { .send-bar {
display: flex; display: flex;
align-items: center; align-items: center;
@ -931,5 +933,5 @@
} }
} }
} }
</style> </style>

10
im-uniapp/pages/chat/chat-group-video.vue

@ -3,8 +3,8 @@
</template> </template>
<script> <script>
import UNI_APP from '@/.env.js' import UNI_APP from '@/.env.js'
export default { export default {
data() { data() {
return { return {
url: "", url: "",
@ -104,11 +104,11 @@
onUnload() { onUnload() {
uni.$off('WS_RTC_GROUP') uni.$off('WS_RTC_GROUP')
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-group-video { .chat-group-video {
.header { .header {
display: flex; display: flex;
justify-content: center; justify-content: center;
@ -135,5 +135,5 @@
} }
} }
} }
} }
</style> </style>

27
im-uniapp/pages/chat/chat-private-video.vue

@ -3,8 +3,8 @@
</template> </template>
<script> <script>
import UNI_APP from '@/.env.js' import UNI_APP from '@/.env.js'
export default { export default {
data() { data() {
return { return {
url: "", url: "",
@ -56,19 +56,19 @@
this.wv = document.getElementById('chat-video-wv').contentWindow this.wv = document.getElementById('chat-video-wv').contentWindow
// #endif // #endif
}, },
initUrl(){ initUrl() {
this.url = "/hybrid/html/rtc-private/index.html"; this.url = "/hybrid/html/rtc-private/index.html";
this.url += "?mode="+this.mode; this.url += "?mode=" + this.mode;
this.url += "&isHost="+this.isHost; this.url += "&isHost=" + this.isHost;
this.url += "&baseUrl="+UNI_APP.BASE_URL; this.url += "&baseUrl=" + UNI_APP.BASE_URL;
this.url += "&loginInfo="+JSON.stringify(uni.getStorageSync("loginInfo")); this.url += "&loginInfo=" + JSON.stringify(uni.getStorageSync("loginInfo"));
this.url += "&userInfo="+JSON.stringify(this.userStore.userInfo); this.url += "&userInfo=" + JSON.stringify(this.userStore.userInfo);
this.url += "&friend="+JSON.stringify(this.friend); this.url += "&friend=" + JSON.stringify(this.friend);
this.url += "&config=" + JSON.stringify(this.configStore.webrtc); this.url += "&config=" + JSON.stringify(this.configStore.webrtc);
}, },
}, },
onBackPress() { onBackPress() {
this.sendMessageToWebView("NAV_BACK",{}) this.sendMessageToWebView("NAV_BACK", {})
}, },
onLoad(options) { onLoad(options) {
uni.$on('WS_RTC_PRIVATE', msg => { uni.$on('WS_RTC_PRIVATE', msg => {
@ -92,12 +92,9 @@
onUnload() { onUnload() {
uni.$off('WS_RTC_PRIVATE') uni.$off('WS_RTC_PRIVATE')
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-web-view {}
.chat-web-view{
}
</style> </style>

27
im-uniapp/pages/chat/chat.vue

@ -11,15 +11,13 @@
<uni-search-bar radius="100" v-model="searchText" cancelButton="none" placeholder="搜索"></uni-search-bar> <uni-search-bar radius="100" v-model="searchText" cancelButton="none" placeholder="搜索"></uni-search-bar>
</view> </view>
</view> </view>
<view class="chat-tip" v-if="!loading && chatStore.chats.length==0"> <view class="chat-tip" v-if="!loading && chatStore.chats.length == 0">
温馨提示您现在还没有任何聊天消息快跟您的好友发起聊天吧~ 温馨提示您现在还没有任何聊天消息快跟您的好友发起聊天吧~
</view> </view>
<scroll-view class="scroll-bar" v-else scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" v-else scroll-with-animation="true" scroll-y="true">
<view v-for="(chat,index) in chatStore.chats" :key="index"> <view v-for="(chat, index) in chatStore.chats" :key="index">
<pop-menu v-if="isShowChat(chat)" :items="menu.items" <pop-menu v-if="isShowChat(chat)" :items="menu.items" @select="onSelectMenu($event, index)">
@select="onSelectMenu($event,index)"> <chat-item :chat="chat" :index="index" :active="menu.chatIdx == index"></chat-item>
<chat-item :chat="chat" :index="index"
:active="menu.chatIdx==index"></chat-item>
</pop-menu> </pop-menu>
</view> </view>
</scroll-view> </scroll-view>
@ -27,9 +25,8 @@
</template> </template>
<script> <script>
import useChatStore from '@/store/chatStore.js'
export default { export default {
data() { data() {
return { return {
showSearch: false, showSearch: false,
@ -55,7 +52,7 @@
} }
}, },
methods: { methods: {
onSelectMenu(item,chatIdx) { onSelectMenu(item, chatIdx) {
switch (item.key) { switch (item.key) {
case 'DELETE': case 'DELETE':
this.removeChat(chatIdx); this.removeChat(chatIdx);
@ -74,8 +71,8 @@
moveToTop(chatIdx) { moveToTop(chatIdx) {
this.chatStore.moveTop(chatIdx); this.chatStore.moveTop(chatIdx);
}, },
isShowChat(chat){ isShowChat(chat) {
if(chat.delete){ if (chat.delete) {
return false; return false;
} }
return !this.searchText || chat.showName.includes(this.searchText) return !this.searchText || chat.showName.includes(this.searchText)
@ -89,7 +86,7 @@
} else { } else {
uni.removeTabBarBadge({ uni.removeTabBarBadge({
index: 0, index: 0,
complete: () => {} complete: () => { }
}) })
} }
} }
@ -116,11 +113,11 @@
onShow() { onShow() {
this.refreshUnreadBadge(); this.refreshUnreadBadge();
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.tab-page { .tab-page {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -153,5 +150,5 @@
flex: 1; flex: 1;
height: 100%; height: 100%;
} }
} }
</style> </style>

18
im-uniapp/pages/common/user-info.vue

@ -9,17 +9,17 @@
<view class="info-item"> <view class="info-item">
<view class="info-primary"> <view class="info-primary">
<text class="info-username"> <text class="info-username">
{{userInfo.userName}} {{ userInfo.userName }}
</text> </text>
<text v-show="userInfo.sex==0" class="iconfont icon-man" color="darkblue"></text> <text v-show="userInfo.sex == 0" class="iconfont icon-man" color="darkblue"></text>
<text v-show="userInfo.sex==1" class="iconfont icon-girl" color="darkred"></text> <text v-show="userInfo.sex == 1" class="iconfont icon-girl" color="darkred"></text>
</view> </view>
<view class="info-text"> <view class="info-text">
<text class="label-text"> <text class="label-text">
昵称: 昵称:
</text> </text>
<text class="content-text"> <text class="content-text">
{{userInfo.nickName}} {{ userInfo.nickName }}
</text> </text>
</view> </view>
<view class="info-text"> <view class="info-text">
@ -28,7 +28,7 @@
签名: 签名:
</text> </text>
<text class="content-text"> <text class="content-text">
{{userInfo.signature}} {{ userInfo.signature }}
</text> </text>
</view> </view>
</view> </view>
@ -45,7 +45,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
userInfo: {} userInfo: {}
@ -156,11 +156,11 @@
// //
this.loadUserInfo(options.id); this.loadUserInfo(options.id);
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.user-info { .user-info {
.content { .content {
height: 200rpx; height: 200rpx;
display: flex; display: flex;
@ -214,5 +214,5 @@
} }
} }
} }
</style> </style>

25
im-uniapp/pages/friend/friend-add.vue

@ -3,17 +3,17 @@
<nav-bar back>添加好友</nav-bar> <nav-bar back>添加好友</nav-bar>
<view class="nav-bar"> <view class="nav-bar">
<view class="nav-search"> <view class="nav-search">
<uni-search-bar v-model="searchText" radius="100" :focus="true" @confirm="onSearch()" @cancel="onCancel()" <uni-search-bar v-model="searchText" radius="100" :focus="true" @confirm="onSearch()"
placeholder="用户名/昵称"></uni-search-bar> @cancel="onCancel()" placeholder="用户名/昵称"></uni-search-bar>
</view> </view>
</view> </view>
<view class="user-items"> <view class="user-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="(user) in users" :key="user.id" v-show="user.id != userStore.userInfo.id"> <view v-for="(user) in users" :key="user.id" v-show="user.id != userStore.userInfo.id">
<view class="user-item"> <view class="user-item">
<head-image :id="user.id" :name="user.nickName" <head-image :id="user.id" :name="user.nickName" :online="user.online"
:online="user.online" :url="user.headImage"></head-image> :url="user.headImage"></head-image>
<view class="user-name">{{ user.nickName}}</view> <view class="user-name">{{ user.nickName }}</view>
<view class="user-btns"> <view class="user-btns">
<button type="primary" v-show="!isFriend(user.id)" size="mini" <button type="primary" v-show="!isFriend(user.id)" size="mini"
@click.stop="onAddFriend(user)">加为好友</button> @click.stop="onAddFriend(user)">加为好友</button>
@ -27,7 +27,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
searchText: "", searchText: "",
@ -75,31 +75,32 @@
return !!friend; return !!friend;
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.friend-add { .friend-add {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.user-items{ .user-items {
position: relative; position: relative;
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
.user-item { .user-item {
height: 120rpx; height: 120rpx;
display: flex; display: flex;
margin-bottom: 1rpx; margin-bottom: 1rpx;
position: relative; position: relative;
padding: 0 30rpx ; padding: 0 30rpx;
align-items: center; align-items: center;
background-color: white; background-color: white;
white-space: nowrap; white-space: nowrap;
.user-name { .user-name {
flex:1; flex: 1;
padding-left: 20rpx; padding-left: 20rpx;
font-size: $im-font-size; font-size: $im-font-size;
line-height: 60rpx; line-height: 60rpx;
@ -113,5 +114,5 @@
} }
} }
} }
</style> </style>

46
im-uniapp/pages/friend/friend.vue

@ -1,34 +1,35 @@
<template> <template>
<nav-bar add search @add="onAddNewFriends" @search="showSearch = !showSearch">好友</nav-bar>
<view class="tab-page friend"> <view class="tab-page friend">
<nav-bar add search @add="onAddNewFriends" @search="showSearch = !showSearch">好友</nav-bar>
<view class="nav-bar" v-if="showSearch"> <view class="nav-bar" v-if="showSearch">
<view class="nav-search"> <view class="nav-search">
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" placeholder="点击搜索好友"></uni-search-bar> <uni-search-bar v-model="searchText" radius="100" cancelButton="none"
placeholder="点击搜索好友"></uni-search-bar>
</view> </view>
</view> </view>
<view class="friend-tip" v-if="friends.length==0"> <view class="friend-tip" v-if="friends.length == 0">
温馨提示您现在还没有任何好友快点击右上方'+'按钮添加好友吧~ 温馨提示您现在还没有任何好友快点击右上方'+'按钮添加好友吧~
</view> </view>
<view class="friend-items" v-else> <view class="friend-items" v-else>
<up-index-list :index-list="friendIdx" > <up-index-list :index-list="friendIdx">
<template v-for="(friends,i) in friendGroups"> <template v-for="(friends, i) in friendGroups">
<up-index-item> <up-index-item>
<up-index-anchor :text="friendIdx[i]=='*'?'在线':friendIdx[i]"></up-index-anchor> <up-index-anchor :text="friendIdx[i] == '*' ? '在线' : friendIdx[i]"></up-index-anchor>
<view v-for="(friend,idx) in friends" :key="idx"> <view v-for="(friend, idx) in friends" :key="idx">
<friend-item :friend="friend"></friend-item> <friend-item :friend="friend"></friend-item>
</view> </view>
</up-index-item> </up-index-item>
</template> </template>
</up-index-list> </up-index-list>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
import { pinyin } from 'pinyin-pro'; import { pinyin } from 'pinyin-pro';
export default { export default {
data() { data() {
return { return {
showSearch: false, showSearch: false,
@ -58,11 +59,11 @@
friends() { friends() {
return this.friendStore.friends; return this.friendStore.friends;
}, },
friendGroupMap(){ friendGroupMap() {
// //
let groupMap = new Map(); let groupMap = new Map();
this.friends.forEach((f) => { this.friends.forEach((f) => {
if(this.searchText && !f.nickName.includes(this.searchText)){ if (this.searchText && !f.nickName.includes(this.searchText)) {
return; return;
} }
let letter = this.firstLetter(f.nickName).toUpperCase(); let letter = this.firstLetter(f.nickName).toUpperCase();
@ -91,35 +92,38 @@
groupMap = new Map(arrayObj.map(i => [i[0], i[1]])); groupMap = new Map(arrayObj.map(i => [i[0], i[1]]));
return groupMap; return groupMap;
}, },
friendIdx(){ friendIdx() {
return Array.from(this.friendGroupMap.keys()); return Array.from(this.friendGroupMap.keys());
}, },
friendGroups(){ friendGroups() {
return Array.from(this.friendGroupMap.values()); return Array.from(this.friendGroupMap.values());
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.friend { .friend {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
:deep(.u-index-anchor){ :deep(.u-index-anchor) {
height: 60rpx !important; height: 60rpx !important;
background-color: unset !important; background-color: unset !important;
border-bottom: none !important; border-bottom: none !important;
} }
:deep(.u-index-anchor__text){
:deep(.u-index-anchor__text) {
color: $im-text-color !important; color: $im-text-color !important;
} }
:deep(.u-index-list__letter__item){
:deep(.u-index-list__letter__item) {
width: 48rpx !important; width: 48rpx !important;
height: 48rpx !important; height: 48rpx !important;
} }
:deep(.u-index-list__letter__item__index){
:deep(.u-index-list__letter__item__index) {
font-size: $im-font-size-small !important; font-size: $im-font-size-small !important;
} }
@ -142,5 +146,5 @@
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

23
im-uniapp/pages/group/group-edit.vue

@ -1,6 +1,6 @@
<template> <template>
<nav-bar back>修改群资料</nav-bar>
<view v-if="userStore.userInfo.type == 1" class="page group-edit"> <view v-if="userStore.userInfo.type == 1" class="page group-edit">
<nav-bar back>修改群资料</nav-bar>
<uni-card :is-shadow="false" is-full :border="false"> <uni-card :is-shadow="false" is-full :border="false">
<uni-forms ref="form" :modelValue="group" :rules="rules" validate-trigger="bind" label-position="top" <uni-forms ref="form" :modelValue="group" :rules="rules" validate-trigger="bind" label-position="top"
label-width="100%"> label-width="100%">
@ -8,8 +8,8 @@
<image-upload v-if="isOwner" :onSuccess="onUnloadImageSuccess"> <image-upload v-if="isOwner" :onSuccess="onUnloadImageSuccess">
<image :src="group.headImageThumb" class="group-image"></image> <image :src="group.headImageThumb" class="group-image"></image>
</image-upload> </image-upload>
<head-image v-if="!isOwner" :name="group.showGroupName" <head-image v-if="!isOwner" :name="group.showGroupName" :url="group.headImageThumb"
:url="group.headImageThumb" :size="200"></head-image> :size="200"></head-image>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="群聊名称" name="name" :required="true"> <uni-forms-item label="群聊名称" name="name" :required="true">
<uni-easyinput type="text" v-model="group.name" :disabled="!isOwner" placeholder="请输入群聊名称" /> <uni-easyinput type="text" v-model="group.name" :disabled="!isOwner" placeholder="请输入群聊名称" />
@ -18,7 +18,8 @@
<uni-easyinput v-model="group.remarkGroupName" type="text" :placeholder="group.name" /> <uni-easyinput v-model="group.remarkGroupName" type="text" :placeholder="group.name" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="我在本群的昵称" name="remarkNickName"> <uni-forms-item label="我在本群的昵称" name="remarkNickName">
<uni-easyinput v-model="group.remarkNickName" type="text" :placeholder="userStore.userInfo.nickName" /> <uni-easyinput v-model="group.remarkNickName" type="text"
:placeholder="userStore.userInfo.nickName" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="群公告" name="notice"> <uni-forms-item label="群公告" name="notice">
<uni-easyinput type="textarea" v-model="group.notice" :disabled="!isOwner" placeholder="请输入群公告" /> <uni-easyinput type="textarea" v-model="group.notice" :disabled="!isOwner" placeholder="请输入群公告" />
@ -30,7 +31,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
group: {}, group: {},
@ -45,7 +46,6 @@
} }
} }
}, },
methods: { methods: {
submit() { submit() {
if (this.group.id) { if (this.group.id) {
@ -136,11 +136,11 @@
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.group-edit { .group-edit {
//padding: 20rpx; //padding: 20rpx;
.group-image { .group-image {
@ -149,8 +149,9 @@
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 5%; border-radius: 5%;
} }
} }
.avatar {
.avatar {
margin-top: -30px; margin-top: -30px;
} }
</style> </style>

45
im-uniapp/pages/group/group-info.vue

@ -3,12 +3,12 @@
<nav-bar back>群聊信息</nav-bar> <nav-bar back>群聊信息</nav-bar>
<view v-if="!group.quit" class="group-members"> <view v-if="!group.quit" class="group-members">
<view class="member-items"> <view class="member-items">
<view v-for="(member,idx) in groupMembers" :key="idx"> <view v-for="(member, idx) in groupMembers" :key="idx">
<view class="member-item" v-if="idx<9"> <view class="member-item" v-if="idx < 9">
<head-image :id="member.userId" :name="member.showNickName" :url="member.headImage" size="small" <head-image :id="member.userId" :name="member.showNickName" :url="member.headImage" size="small"
:online="member.online" ></head-image> :online="member.online"></head-image>
<view class="member-name"> <view class="member-name">
<text>{{member.showNickName}}</text> <text>{{ member.showNickName }}</text>
</view> </view>
</view> </view>
</view> </view>
@ -16,29 +16,28 @@
<uni-icons type="plusempty" size="20" color="#888888"></uni-icons> <uni-icons type="plusempty" size="20" color="#888888"></uni-icons>
</view> </view>
</view> </view>
<view class="member-more" @click="onShowMoreMmeber()">{{`查看全部群成员${groupMembers.length}`}}></view> <view class="member-more" @click="onShowMoreMmeber()">{{ `查看全部群成员${groupMembers.length}` }}></view>
</view> </view>
<view class="group-detail"> <view class="group-detail">
<uni-section title="群聊名称"> <uni-section title="群聊名称">
<template v-slot:right> <template v-slot:right>
<text class="detail-text">{{group.name}}</text> <text class="detail-text">{{ group.name }}</text>
</template> </template>
</uni-section> </uni-section>
<uni-section title="群主"> <uni-section title="群主">
<template v-slot:right> <template v-slot:right>
<text class="detail-text">{{ownerName}}</text> <text class="detail-text">{{ ownerName }}</text>
</template> </template>
</uni-section> </uni-section>
<uni-section title="群名备注"> <uni-section title="群名备注">
<template v-slot:right> <template v-slot:right>
<text class="detail-text"> {{group.remarkGroupName}}</text> <text class="detail-text"> {{ group.remarkGroupName }}</text>
</template> </template>
</uni-section> </uni-section>
<uni-section title="我在本群的昵称"> <uni-section title="我在本群的昵称">
<template v-slot:right> <template v-slot:right>
<text class="detail-text"> {{group.showNickName}}</text> <text class="detail-text"> {{ group.showNickName }}</text>
</template> </template>
</uni-section> </uni-section>
<uni-section v-if="group.notice" title="群公告"> <uni-section v-if="group.notice" title="群公告">
@ -55,16 +54,16 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
groupId: null, groupId: null,
group:{}, group: {},
groupMembers: [] groupMembers: []
} }
}, },
methods: { methods: {
onFocusSearch() {}, onFocusSearch() { },
onInviteMember() { onInviteMember() {
uni.navigateTo({ uni.navigateTo({
url: `/pages/group/group-invite?id=${this.groupId}` url: `/pages/group/group-invite?id=${this.groupId}`
@ -109,13 +108,13 @@
content: `您已退出群聊'${this.group.name}'`, content: `您已退出群聊'${this.group.name}'`,
showCancel: false, showCancel: false,
success: () => { success: () => {
setTimeout(()=>{ setTimeout(() => {
uni.switchTab({ uni.switchTab({
url:"/pages/group/group" url: "/pages/group/group"
}); });
this.groupStore.removeGroup(this.groupId); this.groupStore.removeGroup(this.groupId);
this.chatStore.removeGroupChat(this.groupId); this.chatStore.removeGroupChat(this.groupId);
},100) }, 100)
} }
}) })
}); });
@ -138,13 +137,13 @@
content: `群聊'${this.group.name}'已解散`, content: `群聊'${this.group.name}'已解散`,
showCancel: false, showCancel: false,
success: () => { success: () => {
setTimeout(()=>{ setTimeout(() => {
uni.switchTab({ uni.switchTab({
url:"/pages/group/group" url: "/pages/group/group"
}); });
this.groupStore.removeGroup(this.groupId); this.groupStore.removeGroup(this.groupId);
this.chatStore.removeGroupChat(this.groupId); this.chatStore.removeGroupChat(this.groupId);
},100) }, 100)
} }
}) })
}); });
@ -192,11 +191,11 @@
this.loadGroupMembers(options.id) this.loadGroupMembers(options.id)
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.group-info { .group-info {
.group-members { .group-members {
padding: 30rpx; padding: 30rpx;
background: white; background: white;
@ -252,7 +251,7 @@
padding: 20rpx 20rpx; padding: 20rpx 20rpx;
background: white; background: white;
.detail-text{ .detail-text {
font-size: $im-font-size; font-size: $im-font-size;
} }
@ -263,5 +262,5 @@
color: $im-text-color-lighter; color: $im-text-color-lighter;
} }
} }
} }
</style> </style>

31
im-uniapp/pages/group/group-invite.vue

@ -2,31 +2,30 @@
<view class="page group-invite"> <view class="page group-invite">
<view class="nav-bar"> <view class="nav-bar">
<view class="nav-search"> <view class="nav-search">
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" placeholder="输入好友昵称搜索"></uni-search-bar> <uni-search-bar v-model="searchText" radius="100" cancelButton="none"
placeholder="输入好友昵称搜索"></uni-search-bar>
</view> </view>
</view> </view>
<view class="friend-items"> <view class="friend-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="friend in friendItems" v-show="!searchText || friend.nickName.includes(searchText)" <view v-for="friend in friendItems" v-show="!searchText || friend.nickName.includes(searchText)"
:key="friend.id"> :key="friend.id">
<view class="friend-item" @click="onSwitchChecked(friend)" :class="{checked: friend.checked, disabled: friend.disabled}"> <view class="friend-item" @click="onSwitchChecked(friend)"
<head-image :name="friend.nickName" :class="{ checked: friend.checked, disabled: friend.disabled }">
:online="friend.online" :url="friend.headImage"></head-image> <head-image :name="friend.nickName" :online="friend.online"
:url="friend.headImage"></head-image>
<view class="friend-name">{{ friend.nickName}}</view> <view class="friend-name">{{ friend.nickName }}</view>
<!-- <view class="friend-checked">-->
<!-- <radio :checked="friend.checked" :disabled="friend.disabled" @click.stop="onSwitchChecked(friend)"/>-->
<!-- </view>-->
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<button class="bottom-btn" type="primary" :disabled="inviteSize==0" @click="onInviteFriends()">邀请({{inviteSize}}) </button> <button class="bottom-btn" type="primary" :disabled="inviteSize == 0"
@click="onInviteFriends()">邀请({{ inviteSize }}) </button>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
groupId: null, groupId: null,
@ -115,11 +114,11 @@
this.groupId = options.id; this.groupId = options.id;
this.loadGroupMembers(options.id); this.loadGroupMembers(options.id);
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.group-invite { .group-invite {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -134,7 +133,7 @@
display: flex; display: flex;
margin-bottom: 1rpx; margin-bottom: 1rpx;
position: relative; position: relative;
padding: 0 30rpx ; padding: 0 30rpx;
align-items: center; align-items: center;
background-color: white; background-color: white;
white-space: nowrap; white-space: nowrap;
@ -148,7 +147,7 @@
} }
.friend-name { .friend-name {
flex:1; flex: 1;
padding-left: 20rpx; padding-left: 20rpx;
font-size: 30rpx; font-size: 30rpx;
font-weight: 600; font-weight: 600;
@ -162,5 +161,5 @@
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

30
im-uniapp/pages/group/group-member.vue

@ -3,25 +3,25 @@
<nav-bar back>群成员</nav-bar> <nav-bar back>群成员</nav-bar>
<view class="nav-bar"> <view class="nav-bar">
<view class="nav-search"> <view class="nav-search">
<uni-search-bar v-model="searchText" radius="100" cancelButton="none" placeholder="输入昵称搜索"></uni-search-bar> <uni-search-bar v-model="searchText" radius="100" cancelButton="none"
placeholder="输入昵称搜索"></uni-search-bar>
</view> </view>
</view> </view>
<view class="member-items"> <view class="member-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="(member,idx) in groupMembers" <view v-for="(member, idx) in groupMembers"
v-show="!searchText || member.showNickName.includes(searchText)" :key="idx"> v-show="!searchText || member.showNickName.includes(searchText)" :key="idx">
<view class="member-item" @click="onShowUserInfo(member.userId)"> <view class="member-item" @click="onShowUserInfo(member.userId)">
<head-image :name="member.showNickName" :online="member.online" :url="member.headImage"></head-image> <head-image :name="member.showNickName" :online="member.online"
<view class="member-name">{{ member.showNickName}} :url="member.headImage"></head-image>
<uni-tag v-if="member.userId==group.ownerId" <view class="member-name">{{ member.showNickName }}
text="群主" size="small" circle type="error"> <uni-tag v-if="member.userId == group.ownerId" text="群主" size="small" circle type="error">
</uni-tag> </uni-tag>
<uni-tag v-if="member.userId==userStore.userInfo.id" <uni-tag v-if="member.userId == userStore.userInfo.id" text="我" size="small" circle></uni-tag>
text="我" size="small" circle></uni-tag>
</view> </view>
<view class="member-kick"> <view class="member-kick">
<button type="warn" plain v-show="isOwner && !isSelf(member.userId)" size="mini" <button type="warn" plain v-show="isOwner && !isSelf(member.userId)" size="mini"
@click.stop="onKickOut(member,idx)">移出群聊</button> @click.stop="onKickOut(member, idx)">移出群聊</button>
</view> </view>
</view> </view>
</view> </view>
@ -31,7 +31,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
isModify: false, isModify: false,
@ -104,11 +104,11 @@
prevPage.$vm.loadGroupMembers(); prevPage.$vm.loadGroupMembers();
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.group-member { .group-member {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -123,7 +123,7 @@
display: flex; display: flex;
margin-bottom: 1rpx; margin-bottom: 1rpx;
position: relative; position: relative;
padding: 0 30rpx ; padding: 0 30rpx;
align-items: center; align-items: center;
background-color: white; background-color: white;
white-space: nowrap; white-space: nowrap;
@ -131,7 +131,7 @@
.member-name { .member-name {
display: flex; display: flex;
align-items: center; align-items: center;
flex:1; flex: 1;
padding-left: 20rpx; padding-left: 20rpx;
font-size: $im-font-size; font-size: $im-font-size;
line-height: $im-font-size * 2; line-height: $im-font-size * 2;
@ -154,5 +154,5 @@
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

13
im-uniapp/pages/group/group.vue

@ -7,13 +7,13 @@
placeholder="点击搜索群聊"></uni-search-bar> placeholder="点击搜索群聊"></uni-search-bar>
</view> </view>
</view> </view>
<view class="group-tip" v-if="groupStore.groups.length==0"> <view class="group-tip" v-if="groupStore.groups.length == 0">
温馨提示您现在还没有加入任何群聊点击右上方'+'按钮可以创建群聊哦~ 温馨提示您现在还没有加入任何群聊点击右上方'+'按钮可以创建群聊哦~
</view> </view>
<view class="group-items" v-else> <view class="group-items" v-else>
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true"> <scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="group in groupStore.groups" :key="group.id"> <view v-for="group in groupStore.groups" :key="group.id">
<group-item v-if="!group.quit&&group.showGroupName.includes(searchText)" <group-item v-if="!group.quit && group.showGroupName.includes(searchText)"
:group="group"></group-item> :group="group"></group-item>
</view> </view>
</scroll-view> </scroll-view>
@ -22,7 +22,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
showSearch: false, showSearch: false,
@ -39,12 +39,11 @@
}) })
} }
} }
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.group { .group {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -69,5 +68,5 @@
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

8
im-uniapp/pages/login/login.vue

@ -17,7 +17,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
loginForm: { loginForm: {
@ -66,11 +66,11 @@
this.loginForm.userName = uni.getStorageSync("userName"); this.loginForm.userName = uni.getStorageSync("userName");
this.loginForm.password = uni.getStorageSync("password"); this.loginForm.password = uni.getStorageSync("password");
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.login { .login {
.title { .title {
padding-top: 150rpx; padding-top: 150rpx;
padding-bottom: 50rpx; padding-bottom: 50rpx;
@ -97,5 +97,5 @@
text-align: center; text-align: center;
font-size: $im-font-size; font-size: $im-font-size;
} }
} }
</style> </style>

34
im-uniapp/pages/mine/mine-edit.vue

@ -2,8 +2,7 @@
<view class="page mine-edit"> <view class="page mine-edit">
<nav-bar back>修改我的信息</nav-bar> <nav-bar back>修改我的信息</nav-bar>
<uni-card :is-shadow="false" is-full :border="false"> <uni-card :is-shadow="false" is-full :border="false">
<uni-forms ref="form" :modelValue="userInfo" label-position="top" <uni-forms ref="form" :modelValue="userInfo" label-position="top" label-width="100%">
label-width="100%">
<uni-forms-item name="headImage" class="avatar"> <uni-forms-item name="headImage" class="avatar">
<image-upload :onSuccess="onUnloadImageSuccess"> <image-upload :onSuccess="onUnloadImageSuccess">
<image :src="userInfo.headImageThumb" class="head-image"></image> <image :src="userInfo.headImageThumb" class="head-image"></image>
@ -16,7 +15,8 @@
<uni-easyinput v-model="userInfo.nickName" type="text" :placeholder="userInfo.userName" /> <uni-easyinput v-model="userInfo.nickName" type="text" :placeholder="userInfo.userName" />
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="性别" name="sex"> <uni-forms-item label="性别" name="sex">
<uni-data-checkbox v-model="userInfo.sex" :localdata="[{text: '男', value: 0}, {text: '女', value: 1}]"></uni-data-checkbox> <uni-data-checkbox v-model="userInfo.sex"
:localdata="[{ text: '男', value: 0 }, { text: '女', value: 1 }]"></uni-data-checkbox>
</uni-forms-item> </uni-forms-item>
<uni-forms-item label="签名" name="signature"> <uni-forms-item label="签名" name="signature">
<uni-easyinput type="textarea" v-model="userInfo.signature" placeholder="编辑个性标签,展示我的独特态度" /> <uni-easyinput type="textarea" v-model="userInfo.signature" placeholder="编辑个性标签,展示我的独特态度" />
@ -28,34 +28,34 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
userInfo: {} userInfo: {}
} }
}, },
methods:{ methods: {
onSexchange(e){ onSexchange(e) {
this.userInfo.sex=e.detail.value; this.userInfo.sex = e.detail.value;
}, },
onUnloadImageSuccess(file, res) { onUnloadImageSuccess(file, res) {
this.userInfo.headImage = res.data.originUrl; this.userInfo.headImage = res.data.originUrl;
this.userInfo.headImageThumb = res.data.thumbUrl; this.userInfo.headImageThumb = res.data.thumbUrl;
}, },
onSubmit(){ onSubmit() {
this.$http({ this.$http({
url: "/user/update", url: "/user/update",
method: "PUT", method: "PUT",
data: this.userInfo data: this.userInfo
}).then(()=>{ }).then(() => {
this.userStore.setUserInfo(this.userInfo); this.userStore.setUserInfo(this.userInfo);
uni.showToast({ uni.showToast({
title:"修改成功", title: "修改成功",
icon: 'none' icon: 'none'
}); });
setTimeout(()=>{ setTimeout(() => {
uni.navigateBack(); uni.navigateBack();
},1000); }, 1000);
}) })
} }
}, },
@ -64,18 +64,18 @@
let mine = this.userStore.userInfo; let mine = this.userStore.userInfo;
this.userInfo = JSON.parse(JSON.stringify(mine)); this.userInfo = JSON.parse(JSON.stringify(mine));
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.mine-edit { .mine-edit {
.head-image { .head-image {
width: 200rpx; width: 200rpx;
height: 200rpx; height: 200rpx;
} }
} }
.avatar { .avatar {
margin-top: -30px; margin-top: -30px;
} }
</style> </style>

17
im-uniapp/pages/mine/mine-password.vue

@ -2,7 +2,7 @@
<view class="page mine-password"> <view class="page mine-password">
<nav-bar back>修改密码</nav-bar> <nav-bar back>修改密码</nav-bar>
<uni-card :is-shadow="false" is-full :border="false"> <uni-card :is-shadow="false" is-full :border="false">
<uni-forms ref="form" :modelValue="formData" label-position="top" label-width="100%" > <uni-forms ref="form" :modelValue="formData" label-position="top" label-width="100%">
<uni-forms-item label="原密码" name="oldPassword"> <uni-forms-item label="原密码" name="oldPassword">
<uni-easyinput type="password" v-model="formData.oldPassword" /> <uni-easyinput type="password" v-model="formData.oldPassword" />
</uni-forms-item> </uni-forms-item>
@ -19,7 +19,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
formData: { formData: {
@ -39,7 +39,7 @@
required: true, required: true,
errorMessage: '请输入新密码', errorMessage: '请输入新密码',
}, { }, {
validateFunction: function(rule, value, data, callback) { validateFunction: function (rule, value, data, callback) {
if (data.confirmPassword != data.newPassword) { if (data.confirmPassword != data.newPassword) {
callback("两次输入的密码不一致"); callback("两次输入的密码不一致");
} }
@ -55,7 +55,7 @@
required: true, required: true,
errorMessage: '请输入确认密码', errorMessage: '请输入确认密码',
}, { }, {
validateFunction: function(rule, value, data, callback) { validateFunction: function (rule, value, data, callback) {
if (data.confirmPassword != data.newPassword) { if (data.confirmPassword != data.newPassword) {
callback("两次输入的密码不一致"); callback("两次输入的密码不一致");
} }
@ -80,9 +80,9 @@
title: "修改密码成功", title: "修改密码成功",
icon: 'none' icon: 'none'
}) })
setTimeout(()=>{ setTimeout(() => {
uni.navigateBack(); uni.navigateBack();
},1000); }, 1000);
}) })
}).catch(err => { }).catch(err => {
console.log('表单错误信息:', err); console.log('表单错误信息:', err);
@ -95,8 +95,7 @@
this.$refs.form.setRules(this.rules) this.$refs.form.setRules(this.rules)
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss"></style>
</style>

26
im-uniapp/pages/mine/mine.vue

@ -3,25 +3,21 @@
<nav-bar>我的</nav-bar> <nav-bar>我的</nav-bar>
<uni-card :is-shadow="false" is-full :border="false"> <uni-card :is-shadow="false" is-full :border="false">
<view class="content" @click="onModifyInfo()"> <view class="content" @click="onModifyInfo()">
<head-image :name="userInfo.nickName" <head-image :name="userInfo.nickName" :url="userInfo.headImage" :size="160"></head-image>
:url="userInfo.headImage"
:size="160"></head-image>
<view class="info-item"> <view class="info-item">
<view class="info-primary"> <view class="info-primary">
<text class="info-username"> <text class="info-username">
{{userInfo.userName}} {{ userInfo.userName }}
</text> </text>
<text v-show="userInfo.sex==0" class="iconfont icon-man" <text v-show="userInfo.sex == 0" class="iconfont icon-man" color="darkblue"></text>
color="darkblue"></text> <text v-show="userInfo.sex == 1" class="iconfont icon-girl" color="darkred"></text>
<text v-show="userInfo.sex==1" class="iconfont icon-girl"
color="darkred"></text>
</view> </view>
<view class="info-text"> <view class="info-text">
<text class="label-text"> <text class="label-text">
昵称: 昵称:
</text> </text>
<text class="content-text"> <text class="content-text">
{{userInfo.nickName}} {{ userInfo.nickName }}
</text> </text>
</view> </view>
<view class="info-text"> <view class="info-text">
@ -30,7 +26,7 @@
签名: 签名:
</text> </text>
<text class="content-text"> <text class="content-text">
{{userInfo.signature}} {{ userInfo.signature }}
</text> </text>
</view> </view>
</view> </view>
@ -50,7 +46,7 @@
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return {} return {}
}, },
@ -84,11 +80,11 @@
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.mine { .mine {
.content { .content {
//height: 200rpx; //height: 200rpx;
display: flex; display: flex;
@ -113,6 +109,7 @@
color: $im-text-color-light; color: $im-text-color-light;
} }
.content-text { .content-text {
font-size: $im-font-size-small; font-size: $im-font-size-small;
color: $im-text-color-light; color: $im-text-color-light;
@ -122,6 +119,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 10rpx; margin-bottom: 10rpx;
.info-username { .info-username {
font-size: $im-font-size-large; font-size: $im-font-size-large;
font-weight: 600; font-weight: 600;
@ -147,5 +145,5 @@
} }
} }
} }
</style> </style>

10
im-uniapp/pages/register/register.vue

@ -16,14 +16,14 @@
</uni-forms-item> </uni-forms-item>
<button class="btn-submit" @click="submit" type="primary">注册并登陆</button> <button class="btn-submit" @click="submit" type="primary">注册并登陆</button>
</uni-forms> </uni-forms>
<navigator class="nav-login" url="/pages/login/login" > <navigator class="nav-login" url="/pages/login/login">
返回登陆页面 返回登陆页面
</navigator> </navigator>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
dataForm: { dataForm: {
@ -108,11 +108,11 @@
}) })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.register { .register {
.title { .title {
padding-top: 150rpx; padding-top: 150rpx;
padding-bottom: 50rpx; padding-bottom: 50rpx;
@ -139,5 +139,5 @@
text-align: center; text-align: center;
font-size: 32rpx; font-size: 32rpx;
} }
} }
</style> </style>

26
im-uniapp/store/chatStore.js

@ -99,7 +99,7 @@ export default defineStore('chatStore', {
} }
} }
}) })
if(!chat.stored){ if (!chat.stored) {
this.saveToStorage(); this.saveToStorage();
} }
}, },
@ -293,7 +293,7 @@ export default defineStore('chatStore', {
} }
}, },
refreshChats() { refreshChats() {
if(!cacheChats){ if (!cacheChats) {
return; return;
} }
// 排序 // 排序
@ -316,17 +316,17 @@ export default defineStore('chatStore', {
let key = "chats-app-" + userId; let key = "chats-app-" + userId;
let chatKeys = []; let chatKeys = [];
// 按会话为单位存储,只存储有改动的会话 // 按会话为单位存储,只存储有改动的会话
this.chats.forEach((chat)=>{ this.chats.forEach((chat) => {
let chatKey = `${key}-${chat.type}-${chat.targetId}` let chatKey = `${key}-${chat.type}-${chat.targetId}`
if(!chat.stored){ if (!chat.stored) {
if(chat.delete){ if (chat.delete) {
uni.removeStorageSync(chatKey); uni.removeStorageSync(chatKey);
}else{ } else {
uni.setStorageSync(chatKey,chat); uni.setStorageSync(chatKey, chat);
} }
chat.stored = true; chat.stored = true;
} }
if(!chat.delete){ if (!chat.delete) {
chatKeys.push(chatKey); chatKeys.push(chatKey);
} }
}) })
@ -353,13 +353,13 @@ export default defineStore('chatStore', {
let userStore = useUserStore(); let userStore = useUserStore();
let userId = userStore.userInfo.id; let userId = userStore.userInfo.id;
let chatsData = uni.getStorageSync("chats-app-" + userId) let chatsData = uni.getStorageSync("chats-app-" + userId)
if(chatsData){ if (chatsData) {
if(chatsData.chatKeys){ if (chatsData.chatKeys) {
let time = new Date().getTime(); let time = new Date().getTime();
chatsData.chats = []; chatsData.chats = [];
chatsData.chatKeys.forEach(key=>{ chatsData.chatKeys.forEach(key => {
let chat = uni.getStorageSync(key); let chat = uni.getStorageSync(key);
if(chat){ if (chat) {
chatsData.chats.push(chat); chatsData.chats.push(chat);
} }
}) })
@ -375,7 +375,7 @@ export default defineStore('chatStore', {
return state.loadingPrivateMsg || state.loadingGroupMsg return state.loadingPrivateMsg || state.loadingGroupMsg
}, },
curChats: (state) => { curChats: (state) => {
if(cacheChats && state.isLoading()){ if (cacheChats && state.isLoading()) {
return cacheChats; return cacheChats;
} }
return state.chats; return state.chats;

2
im-uniapp/store/userStore.js

@ -14,7 +14,7 @@ export default defineStore('userStore', {
clear() { clear() {
this.userInfo = {}; this.userInfo = {};
}, },
loadUser(context) { loadUser() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
http({ http({
url: '/user/self', url: '/user/self',

2
im-uniapp/vite.config.js

@ -1,7 +1,5 @@
import { defineConfig } from "vite" import { defineConfig } from "vite"
import uni from "@dcloudio/vite-plugin-uni"; import uni from "@dcloudio/vite-plugin-uni";
const path = require('path')
const fs = require('fs')
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
uni() uni()

1
im-web/src/view/Login.vue

@ -29,7 +29,6 @@
</div> </div>
<icp></icp> <icp></icp>
</div> </div>
</template> </template>
<script> <script>

Loading…
Cancel
Save