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

6
im-uniapp/common/date.js

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

52
im-uniapp/common/enums.js

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

24
im-uniapp/common/messageType.js

@ -1,32 +1,32 @@
// 是否普通消息
let isNormal = function(type){
return type>=0 && type < 10;
let isNormal = function (type) {
return type >= 0 && type < 10;
}
// 是否状态消息
let isStatus = function(type){
return type>=10 && type < 20;
let isStatus = function (type) {
return type >= 10 && type < 20;
}
// 是否提示消息
let isTip = function(type){
return type>=20 && type < 30;
let isTip = function (type) {
return type >= 20 && type < 30;
}
// 操作交互类消息
let isAction = function(type){
return type>=40 && type < 50;
let isAction = function (type) {
return type >= 40 && type < 50;
}
// 单人通话信令
let isRtcPrivate = function(type){
return type>=100 && type < 200;
let isRtcPrivate = function (type) {
return type >= 100 && type < 200;
}
// 多人通话信令
let isRtcGroup = function(type){
return type>=200 && type < 300;
let isRtcGroup = function (type) {
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 start = () => {
if(rc != null){
if (rc != null) {
close();
}
rc = new Recorder();
@ -22,7 +22,7 @@ let close = () => {
let upload = () => {
return new Promise((resolve, reject) => {
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 file = new File([newbolb], name)
uni.uploadFile({
@ -34,10 +34,10 @@ let upload = () => {
name: 'file',
success: (res) => {
let r = JSON.parse(res.data);
if(r.code != 200){
if (r.code != 200) {
console.log(res)
reject(r.message);
}else {
} else {
const data = {
duration: parseInt(rc.duration),
url: r.data

4
im-uniapp/common/request.js

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

10
im-uniapp/common/wssocket.js

@ -55,7 +55,7 @@ let init = () => {
console.log(e)
isConnect = false;
// 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 delay = timeDiff < 10000 ? 10000 - timeDiff : 0;
rec && clearTimeout(rec);
rec = setTimeout(function() {
rec = setTimeout(function () {
connect(wsurl, accessToken);
}, delay);
};
@ -119,7 +119,7 @@ let close = (code) => {
var heartCheck = {
timeout: 10000, //每段时间发送一次心跳包 这里设置为30s
timeoutObj: null, //延时发送消息对象(启动心跳新建这个对象,收到消息后重置对象)
start: function() {
start: function () {
if (isConnect) {
console.log('发送WebSocket心跳')
let heartBeat = {
@ -134,9 +134,9 @@ var heartCheck = {
})
}
},
reset: function() {
reset: function () {
clearTimeout(this.timeoutObj);
this.timeoutObj = setTimeout(function() {
this.timeoutObj = setTimeout(function () {
heartCheck.start();
}, this.timeout);
}

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

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

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

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

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

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

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

@ -1,12 +1,12 @@
<template>
<view class="switch-bar">
<text class="title">{{title}}</text>
<text class="title">{{ title }}</text>
<switch class="switch" :checked="checked" color="#18bc37" @change="onChange"></switch>
</view>
</template>
<script>
export default {
export default {
name: "switch-bar",
props: {
title: {
@ -26,20 +26,20 @@
methods: {
onChange(e) {
this.value = true;
setTimeout(()=>{
setTimeout(() => {
this.value = false;
},100)
}, 100)
//this.value = false;
this.$emit('change', e);
}
}
}
}
</script>
<style lang="scss" scoped>
.switch-bar {
.switch-bar {
width: 100%;
height: 100rpx;
font-size: 34rpx;
@ -57,5 +57,5 @@
.switch {
margin-right: 40rpx;
}
}
}
</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-tip"> 选择要提醒的人</view>
<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>
</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 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>
</view>
</view>
@ -19,15 +19,14 @@
</view>
<view class="member-items">
<scroll-view class="scroll-bar" scroll-with-animation="true" scroll-y="true">
<view v-for="m in showMembers" v-show="m.showNickName.includes(searchText)"
:key="m.userId">
<view class="member-item" :class="{checked: m.checked}" @click="onSwitchChecked(m)">
<view v-for="m in showMembers" v-show="m.showNickName.includes(searchText)" :key="m.userId">
<view class="member-item" :class="{ checked: m.checked }" @click="onSwitchChecked(m)">
<head-image :name="m.showNickName" :online="m.online" :url="m.headImage"
size="small"></head-image>
<view class="member-name">{{ m.showNickName}}</view>
<!-- <view class="member-checked">-->
<!-- <radio :checked="m.checked" @click.stop="onSwitchChecked(m)" />-->
<!-- </view>-->
<view class="member-name">{{ m.showNickName }}</view>
<!-- <view class="member-checked">-->
<!-- <radio :checked="m.checked" @click.stop="onSwitchChecked(m)" />-->
<!-- </view>-->
</view>
</view>
</scroll-view>
@ -37,7 +36,7 @@
</template>
<script>
export default {
export default {
name: "chat-at-box",
props: {
ownerId: {
@ -50,21 +49,21 @@
data() {
return {
searchText: "",
showMembers:[]
showMembers: []
};
},
methods: {
init(atUserIds) {
this.showMembers = [];
let userId = this.userStore.userInfo.id;
if(this.ownerId == userId){
if (this.ownerId == userId) {
this.showMembers.push({
userId:-1,
userId: -1,
showNickName: "全体成员"
})
}
this.members.forEach((m) => {
if(!m.quit && m.userId != userId){
if (!m.quit && m.userId != userId) {
m.checked = atUserIds.indexOf(m.userId) >= 0;
this.showMembers.push(m);
}
@ -101,12 +100,12 @@
return ids;
}
}
}
}
</script>
<style lang="scss" scoped>
.chat-at-box {
.chat-at-box {
position: relative;
display: flex;
flex-direction: column;
@ -175,5 +174,5 @@
height: 800rpx;
}
}
}
}
</style>

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

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

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

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

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

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

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

@ -1,8 +1,8 @@
<template>
<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">
{{recording?'正在录音':'长按 说话'}}</view>
{{ recording ? '正在录音' : '长按 说话' }}</view>
<view v-if="recording" class="chat-record-window" :style="recordWindowStyle">
<view class="rc-wave">
<text class="note" style="--d: 0"></text>
@ -13,18 +13,18 @@
<text class="note" style="--d: 5"></text>
<text class="note" style="--d: 6"></text>
</view>
<view class="rc-tip">{{recordTip}}</view>
<view class="rc-tip">{{ recordTip }}</view>
<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 class="opt-tip" :class="moveToCancel?'red':'black'">{{moveToCancel? '松手取消':'松手发送,上划取消'}}</view>
<view class="opt-tip" :class="moveToCancel ? 'red' : 'black'">{{ moveToCancel ? '松手取消' : '松手发送,上划取消' }}</view>
</view>
</view>
</template>
<script>
export default {
export default {
name: "chat-record",
data() {
return {
@ -132,17 +132,17 @@
},
recordTip() {
if (this.druation > 50) {
return `${60-this.druation}s后将停止录音`;
return `${60 - this.druation}s后将停止录音`;
}
return `录音时长:${this.druation}s`;
}
}
}
}
</script>
<style lang="scss" scoped>
.chat-record {
.chat-record {
.rc-wave {
display: flex;
align-items: flex-end;
@ -234,5 +234,5 @@
}
}
}
}
</style>

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

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

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

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

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

@ -1,23 +1,22 @@
<template>
<view class="group-item" @click="showGroupInfo()">
<head-image :name="group.showGroupName"
:url="group.headImage" size="small"></head-image>
<head-image :name="group.showGroupName" :url="group.headImage" size="small"></head-image>
<view class="group-name">
<view>{{ group.showGroupName}}</view>
<view>{{ group.showGroupName }}</view>
</view>
</view>
</template>
<script>
export default {
export default {
name: "group-item",
data() {
return {}
},
methods:{
showGroupInfo(){
methods: {
showGroupInfo() {
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
}
}
}
}
</script>
<style scope lang="scss">
.group-item {
.group-item {
height: 90rpx;
display: flex;
margin-bottom: 2rpx;
@ -55,5 +54,5 @@
white-space: nowrap;
overflow: hidden;
}
}
}
</style>

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

@ -4,12 +4,12 @@
<view class="top-bar">
<view class="top-tip">选择成员</view>
<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>
</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 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>
</view>
</view>
@ -23,7 +23,7 @@
<view class="member-item" @click="onSwitchChecked(m)">
<head-image :name="m.showNickName" :online="m.online" :url="m.headImage"
:size="90"></head-image>
<view class="member-name">{{ m.showNickName}}</view>
<view class="member-name">{{ m.showNickName }}</view>
<view class="member-checked">
<radio :checked="m.checked" :disabled="m.locked" @click.stop="onSwitchChecked(m)" />
</view>
@ -37,7 +37,7 @@
<script>
export default {
export default {
name: "chat-group-member-choose",
props: {
members: {
@ -102,12 +102,12 @@
return ids;
}
}
}
}
</script>
<style lang="scss" scoped>
.chat-group-member-choose {
.chat-group-member-choose {
position: relative;
display: flex;
flex-direction: column;
@ -135,6 +135,7 @@
align-items: center;
height: 90rpx;
padding: 0 30rpx;
.user-item {
padding: 3rpx;
}
@ -169,5 +170,5 @@
height: 800rpx;
}
}
}
}
</style>

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

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

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

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

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

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

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

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

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

@ -11,9 +11,11 @@
<slot></slot>
</view>
<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="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>
@ -85,8 +87,7 @@ export default {
box-sizing: border-box;
height: $im-nav-bar-height;
.title {
}
.title {}
.back {
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="menu" :style="menuStyle">
<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>
</template>
<script>
export default {
export default {
name: "pop-menu",
data() {
return {
isShowMenu : false,
isShowMenu: false,
isTouchMove: false,
style : ""
style: ""
}
},
props: {
@ -29,8 +28,8 @@
}
},
methods: {
onLongPress(e){
if(this.isTouchMove){
onLongPress(e) {
if (this.isTouchMove) {
//
return;
}
@ -40,12 +39,12 @@
let style = "";
/* 因 非H5端不兼容 style 属性绑定 Object ,所以拼接字符 */
if (touches.clientY > (res.windowHeight / 2)) {
style = `bottom:${res.windowHeight-touches.clientY}px;`;
style = `bottom:${res.windowHeight - touches.clientY}px;`;
} else {
style = `top:${touches.clientY}px;`;
}
if (touches.clientX > (res.windowWidth / 2)) {
style += `right:${res.windowWidth-touches.clientX}px;`;
style += `right:${res.windowWidth - touches.clientX}px;`;
} else {
style += `left:${touches.clientX}px;`;
}
@ -57,11 +56,11 @@
}
})
},
onTouchMove(){
onTouchMove() {
this.onClose();
this.isTouchMove = true;
},
onTouchEnd(){
onTouchEnd() {
this.isTouchMove = false;
},
onSelectMenu(item) {
@ -71,18 +70,18 @@
onClose() {
this.isShowMenu = false;
},
itemStyle(item){
if(item.color){
itemStyle(item) {
if (item.color) {
return `color:${item.color};`
}
// return `color:#4f76e6;`;
}
}
}
}
</script>
<style lang="scss" scoped>
.pop-menu {
.pop-menu {
position: fixed;
left: 0;
top: 0;
@ -91,15 +90,16 @@
width: 100%;
height: 100%;
z-index: 999;
}
}
.menu {
.menu {
position: fixed;
border-radius: 4px;
overflow: hidden;
background-color: #fff;
z-index: 1000;
box-shadow: $im-box-shadow-dark;
.menu-item {
height: 28px;
min-width: 120rpx;
@ -117,5 +117,5 @@
margin-right: 10rpx;
}
}
}
}
</style>

5
im-uniapp/main.js

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

167
im-uniapp/manifest.json

@ -1,32 +1,32 @@
{
"name" : "盒子IM",
"appid" : "__UNI__69DD57A",
"description" : "",
"versionName" : "3.1.0",
"versionCode" : 3100,
"transformPx" : false,
"name": "盒子IM",
"appid": "__UNI__69DD57A",
"description": "",
"versionName": "3.1.0",
"versionCode": 3100,
"transformPx": false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* */
"modules" : {
"Camera" : {},
"Record" : {},
"Bluetooth" : {}
"modules": {
"Camera": {},
"Record": {},
"Bluetooth": {}
},
/* */
"distribute" : {
"distribute": {
/* android */
"android" : {
"permissions" : [
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<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.RECORD_AUDIO\" />"
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
"minSdkVersion" : 21
"abiFilters": [
"armeabi-v7a",
"arm64-v8a",
"x86"
],
"minSdkVersion": 21
},
/* ios */
"ios" : {
"dSYMs" : false,
"privacyDescription" : {
"NSMicrophoneUsageDescription" : "",
"NSCameraUsageDescription" : ""
"ios": {
"dSYMs": false,
"privacyDescription": {
"NSMicrophoneUsageDescription": "",
"NSCameraUsageDescription": ""
},
"idfa" : false
"idfa": false
},
/* SDK */
"sdkConfigs" : {
"ad" : {},
"speech" : {}
"sdkConfigs": {
"ad": {},
"speech": {}
},
"icons" : {
"android" : {
"xhdpi" : "unpackage/res/icons/96x96.png",
"hdpi" : "unpackage/res/icons/72x72.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
"icons": {
"android": {
"xhdpi": "unpackage/res/icons/96x96.png",
"hdpi": "unpackage/res/icons/72x72.png",
"xxhdpi": "unpackage/res/icons/144x144.png",
"xxxhdpi": "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
"ios": {
"appstore": "unpackage/res/icons/1024x1024.png",
"ipad": {
"app": "unpackage/res/icons/76x76.png",
"app@2x": "unpackage/res/icons/152x152.png",
"notification": "unpackage/res/icons/20x20.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"proapp@2x": "unpackage/res/icons/167x167.png",
"settings": "unpackage/res/icons/29x29.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"spotlight": "unpackage/res/icons/40x40.png",
"spotlight@2x": "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
"iphone": {
"app@2x": "unpackage/res/icons/120x120.png",
"app@3x": "unpackage/res/icons/180x180.png",
"notification@2x": "unpackage/res/icons/40x40.png",
"notification@3x": "unpackage/res/icons/60x60.png",
"settings@2x": "unpackage/res/icons/58x58.png",
"settings@3x": "unpackage/res/icons/87x87.png",
"spotlight@2x": "unpackage/res/icons/80x80.png",
"spotlight@3x": "unpackage/res/icons/120x120.png"
}
}
}
}
},
/* */
"quickapp" : {},
"quickapp": {},
/* */
"mp-weixin" : {
"appid" : "wxda94f40bfad0262c",
"libVersion" : "latest",
"setting" : {
"urlCheck" : false
"mp-weixin": {
"appid": "wxda94f40bfad0262c",
"libVersion": "latest",
"setting": {
"urlCheck": false
},
"usingComponents" : true
"usingComponents": true
},
"mp-alipay" : {
"usingComponents" : true
"mp-alipay": {
"usingComponents": true
},
"mp-baidu" : {
"usingComponents" : true
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao" : {
"usingComponents" : true
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics" : {
"enable" : false
"uniStatistics": {
"enable": false
},
"vueVersion" : "3",
"h5" : {
"title" : "盒子IM",
"router" : {
"base" : "/h5/"
"vueVersion": "3",
"h5": {
"title": "盒子IM",
"router": {
"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"
}
},
"pages": [{
"pages": [
{
"path": "pages/login/login"
}, {
"path" : "pages/register/register"
},{
},
{
"path": "pages/register/register"
},
{
"path": "pages/chat/chat"
}, {
},
{
"path": "pages/friend/friend"
}, {
},
{
"path": "pages/group/group"
}, {
},
{
"path": "pages/mine/mine"
}, {
},
{
"path": "pages/common/user-info"
}, {
},
{
"path": "pages/chat/chat-box"
},{
},
{
"path": "pages/chat/chat-private-video"
},{
},
{
"path": "pages/chat/chat-group-video"
}, {
},
{
"path": "pages/friend/friend-add"
}, {
},
{
"path": "pages/group/group-info"
}, {
},
{
"path": "pages/group/group-edit"
}, {
},
{
"path": "pages/group/group-invite"
}, {
},
{
"path": "pages/group/group-member"
}, {
},
{
"path": "pages/mine/mine-edit"
},{
},
{
"path": "pages/mine/mine-password"
}
],
@ -53,12 +70,12 @@
"selectedColor": "#587ff0",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"list": [
{
"pagePath": "pages/chat/chat",
"iconPath": "static/tarbar/chat.png",
"selectedIconPath": "static/tarbar/chat_active.png",
"text": "消息"
},
{
"pagePath": "pages/friend/friend",

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

@ -1,21 +1,21 @@
<template>
<view class="page chat-box">
<nav-bar back more @more="onShowMore">{{title}}</nav-bar>
<view class="chat-msg" @click="switchChatTabBox('none',true)">
<nav-bar back more @more="onShowMore">{{ title }}</nav-bar>
<view class="chat-msg" @click="switchChatTabBox('none', true)">
<scroll-view class="scroll-box" scroll-y="true" upper-threshold="200" @scrolltoupper="onScrollToTop"
:scroll-into-view="'chat-item-'+scrollMsgIdx">
<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)"
:scroll-into-view="'chat-item-' + scrollMsgIdx">
<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)"
:showName="showName(msgInfo)" @recall="onRecallMessage" @copy="onCopyMessage"
@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>
</view>
</scroll-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>
<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 v-for="m in atUserItems" class="chat-at-item">
<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>
<view v-else class="send-text">
<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
:hold-keyboard="true"></textarea>
</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 v-if="sendText==''" class="iconfont icon-add" @click="onShowToolsChatTab()">
<view v-if="sendText == ''" class="iconfont icon-add" @click="onShowToolsChatTab()">
</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>
</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 class="chat-tools-item">
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore"
@ -71,7 +72,7 @@
<view class="tool-name">语音消息</view>
</view>
<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>
<!-- #ifndef MP-WEIXIN -->
@ -90,7 +91,7 @@
</view>
<!-- #endif -->
</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">
<image class="emotion-item" :title="emoText" :src="$emo.textToPath(emoText)"
v-for="(emoText, i) in $emo.emoTextList" :key="i" @click="selectEmoji(emoText)" mode="aspectFit"
@ -112,9 +113,9 @@
</template>
<script>
import UNI_APP from '@/.env.js';
import UNI_APP from '@/.env.js';
export default {
export default {
data() {
return {
chat: {},
@ -707,7 +708,7 @@
}
},
watch: {
messageSize: function(newSize, oldSize) {
messageSize: function (newSize, oldSize) {
//
if (newSize > oldSize) {
let pages = getCurrentPages();
@ -759,11 +760,11 @@
this.needScrollToBottom = false;
}
}
}
}
</script>
<style lang="scss" scoped>
.chat-box {
.chat-box {
position: relative;
display: flex;
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 {
display: flex;
align-items: center;
@ -931,5 +933,5 @@
}
}
}
}
</style>

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

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

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

@ -3,8 +3,8 @@
</template>
<script>
import UNI_APP from '@/.env.js'
export default {
import UNI_APP from '@/.env.js'
export default {
data() {
return {
url: "",
@ -56,19 +56,19 @@
this.wv = document.getElementById('chat-video-wv').contentWindow
// #endif
},
initUrl(){
initUrl() {
this.url = "/hybrid/html/rtc-private/index.html";
this.url += "?mode="+this.mode;
this.url += "&isHost="+this.isHost;
this.url += "&baseUrl="+UNI_APP.BASE_URL;
this.url += "&loginInfo="+JSON.stringify(uni.getStorageSync("loginInfo"));
this.url += "&userInfo="+JSON.stringify(this.userStore.userInfo);
this.url += "&friend="+JSON.stringify(this.friend);
this.url += "?mode=" + this.mode;
this.url += "&isHost=" + this.isHost;
this.url += "&baseUrl=" + UNI_APP.BASE_URL;
this.url += "&loginInfo=" + JSON.stringify(uni.getStorageSync("loginInfo"));
this.url += "&userInfo=" + JSON.stringify(this.userStore.userInfo);
this.url += "&friend=" + JSON.stringify(this.friend);
this.url += "&config=" + JSON.stringify(this.configStore.webrtc);
},
},
onBackPress() {
this.sendMessageToWebView("NAV_BACK",{})
this.sendMessageToWebView("NAV_BACK", {})
},
onLoad(options) {
uni.$on('WS_RTC_PRIVATE', msg => {
@ -92,12 +92,9 @@
onUnload() {
uni.$off('WS_RTC_PRIVATE')
}
}
}
</script>
<style lang="scss" scoped>
.chat-web-view{
}
.chat-web-view {}
</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>
</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>
<scroll-view class="scroll-bar" v-else scroll-with-animation="true" scroll-y="true">
<view v-for="(chat,index) in chatStore.chats" :key="index">
<pop-menu v-if="isShowChat(chat)" :items="menu.items"
@select="onSelectMenu($event,index)">
<chat-item :chat="chat" :index="index"
:active="menu.chatIdx==index"></chat-item>
<view v-for="(chat, index) in chatStore.chats" :key="index">
<pop-menu v-if="isShowChat(chat)" :items="menu.items" @select="onSelectMenu($event, index)">
<chat-item :chat="chat" :index="index" :active="menu.chatIdx == index"></chat-item>
</pop-menu>
</view>
</scroll-view>
@ -27,9 +25,8 @@
</template>
<script>
import useChatStore from '@/store/chatStore.js'
export default {
export default {
data() {
return {
showSearch: false,
@ -55,7 +52,7 @@
}
},
methods: {
onSelectMenu(item,chatIdx) {
onSelectMenu(item, chatIdx) {
switch (item.key) {
case 'DELETE':
this.removeChat(chatIdx);
@ -74,8 +71,8 @@
moveToTop(chatIdx) {
this.chatStore.moveTop(chatIdx);
},
isShowChat(chat){
if(chat.delete){
isShowChat(chat) {
if (chat.delete) {
return false;
}
return !this.searchText || chat.showName.includes(this.searchText)
@ -89,7 +86,7 @@
} else {
uni.removeTabBarBadge({
index: 0,
complete: () => {}
complete: () => { }
})
}
}
@ -116,11 +113,11 @@
onShow() {
this.refreshUnreadBadge();
}
}
}
</script>
<style scoped lang="scss">
.tab-page {
.tab-page {
position: relative;
display: flex;
flex-direction: column;
@ -153,5 +150,5 @@
flex: 1;
height: 100%;
}
}
}
</style>

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

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

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

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

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

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

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

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

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

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

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

@ -2,31 +2,30 @@
<view class="page group-invite">
<view class="nav-bar">
<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 class="friend-items">
<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)"
:key="friend.id">
<view class="friend-item" @click="onSwitchChecked(friend)" :class="{checked: friend.checked, disabled: friend.disabled}">
<head-image :name="friend.nickName"
:online="friend.online" :url="friend.headImage"></head-image>
<view class="friend-name">{{ friend.nickName}}</view>
<!-- <view class="friend-checked">-->
<!-- <radio :checked="friend.checked" :disabled="friend.disabled" @click.stop="onSwitchChecked(friend)"/>-->
<!-- </view>-->
<view class="friend-item" @click="onSwitchChecked(friend)"
:class="{ checked: friend.checked, disabled: friend.disabled }">
<head-image :name="friend.nickName" :online="friend.online"
:url="friend.headImage"></head-image>
<view class="friend-name">{{ friend.nickName }}</view>
</view>
</view>
</scroll-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>
</template>
<script>
export default {
export default {
data() {
return {
groupId: null,
@ -115,11 +114,11 @@
this.groupId = options.id;
this.loadGroupMembers(options.id);
}
}
}
</script>
<style lang="scss" scoped>
.group-invite {
.group-invite {
position: relative;
display: flex;
flex-direction: column;
@ -134,7 +133,7 @@
display: flex;
margin-bottom: 1rpx;
position: relative;
padding: 0 30rpx ;
padding: 0 30rpx;
align-items: center;
background-color: white;
white-space: nowrap;
@ -148,7 +147,7 @@
}
.friend-name {
flex:1;
flex: 1;
padding-left: 20rpx;
font-size: 30rpx;
font-weight: 600;
@ -162,5 +161,5 @@
height: 100%;
}
}
}
}
</style>

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

@ -3,25 +3,25 @@
<nav-bar back>群成员</nav-bar>
<view class="nav-bar">
<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 class="member-items">
<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">
<view class="member-item" @click="onShowUserInfo(member.userId)">
<head-image :name="member.showNickName" :online="member.online" :url="member.headImage"></head-image>
<view class="member-name">{{ member.showNickName}}
<uni-tag v-if="member.userId==group.ownerId"
text="群主" size="small" circle type="error">
<head-image :name="member.showNickName" :online="member.online"
:url="member.headImage"></head-image>
<view class="member-name">{{ member.showNickName }}
<uni-tag v-if="member.userId == group.ownerId" text="群主" size="small" circle type="error">
</uni-tag>
<uni-tag v-if="member.userId==userStore.userInfo.id"
text="我" size="small" circle></uni-tag>
<uni-tag v-if="member.userId == userStore.userInfo.id" text="我" size="small" circle></uni-tag>
</view>
<view class="member-kick">
<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>
@ -31,7 +31,7 @@
</template>
<script>
export default {
export default {
data() {
return {
isModify: false,
@ -104,11 +104,11 @@
prevPage.$vm.loadGroupMembers();
}
}
}
}
</script>
<style scoped lang="scss">
.group-member {
.group-member {
position: relative;
display: flex;
flex-direction: column;
@ -123,7 +123,7 @@
display: flex;
margin-bottom: 1rpx;
position: relative;
padding: 0 30rpx ;
padding: 0 30rpx;
align-items: center;
background-color: white;
white-space: nowrap;
@ -131,7 +131,7 @@
.member-name {
display: flex;
align-items: center;
flex:1;
flex: 1;
padding-left: 20rpx;
font-size: $im-font-size;
line-height: $im-font-size * 2;
@ -154,5 +154,5 @@
height: 100%;
}
}
}
}
</style>

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

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

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

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

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

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

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

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

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

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

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

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

26
im-uniapp/store/chatStore.js

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

2
im-uniapp/store/userStore.js

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

2
im-uniapp/vite.config.js

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

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

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

Loading…
Cancel
Save