Browse Source

适配ios小程序

master
xsx 7 months ago
parent
commit
24ea5fd2d3
  1. 22
      im-uniapp/App.vue
  2. 18
      im-uniapp/components/chat-message-item/chat-message-item.vue
  3. 203
      im-uniapp/components/nav-bar/nav-bar.vue
  4. 10
      im-uniapp/pages.json
  5. 238
      im-uniapp/pages/chat/chat-box.vue

22
im-uniapp/App.vue

@ -492,6 +492,9 @@ uni-page-head {
} }
// #endif // #endif
page {
background-color: $im-bg;
}
.tab-page { .tab-page {
position: relative; position: relative;
@ -502,9 +505,15 @@ uni-page-head {
top: $im-nav-bar-height; top: $im-nav-bar-height;
// #endif // #endif
// #ifndef H5 // #ifdef APP-PLUS
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app
top: calc($im-nav-bar-height + var(--status-bar-height)); top: calc($im-nav-bar-height + var(--status-bar-height));
// #endif
// #ifdef MP-WEIXIN
height: calc(100vh - $im-nav-bar-height);
top: $im-nav-bar-height;
// #endif // #endif
color: $im-text-color; color: $im-text-color;
background-color: $im-bg; background-color: $im-bg;
@ -515,13 +524,20 @@ uni-page-head {
.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); // h5100vh
top: $im-nav-bar-height; top: $im-nav-bar-height;
// #endif // #endif
// #ifndef H5
// #ifdef APP-PLUS
height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app height: calc(100vh - var(--status-bar-height) - $im-nav-bar-height); // app
top: calc($im-nav-bar-height + var(--status-bar-height)); top: calc($im-nav-bar-height + var(--status-bar-height));
// #endif // #endif
// #ifdef MP-WEIXIN
height: calc(100vh - $im-nav-bar-height);
top: $im-nav-bar-height;
// #endif
color: $im-text-color; color: $im-text-color;
background-color: $im-bg; background-color: $im-bg;
font-size: $im-font-size; font-size: $im-font-size;

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

@ -56,21 +56,21 @@
<text v-if="audioPlayState == 'PLAYING'" class="iconfont icon-pause"></text> <text v-if="audioPlayState == 'PLAYING'" class="iconfont icon-pause"></text>
</view> </view>
</long-press-menu> </long-press-menu>
<long-press-menu v-if="isAction" :items="menuItems" @select="onSelectMenu">
<view class="chat-realtime message-text" @click="$emit('call')">
<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"
class="iconfont icon-chat-video"></text>
<text>{{ msgInfo.content }}</text>
</view>
</long-press-menu>
<view v-if="sending&&isTextMessage" class="sending"> <view v-if="sending&&isTextMessage" class="sending">
<loading :size="40" icon-color="#656adf" :mask="false"></loading> <loading :size="40" icon-color="#656adf" :mask="false"></loading>
</view> </view>
<view v-else-if="sendFail" @click="onSendFail" <view v-else-if="sendFail" @click="onSendFail"
class="send-fail iconfont icon-warning-circle-fill"></view> class="send-fail iconfont icon-warning-circle-fill"></view>
</view> </view>
<long-press-menu v-if="isAction" :items="menuItems" @select="onSelectMenu">
<view class="chat-realtime message-text" @click="$emit('call')">
<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"
class="iconfont icon-chat-video"></text>
<text>{{ msgInfo.content }}</text>
</view>
</long-press-menu>
<view class="message-status" v-if="!isAction && msgInfo.selfSend && !msgInfo.groupId"> <view class="message-status" v-if="!isAction && msgInfo.selfSend && !msgInfo.groupId">
<text class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</text> <text class="chat-readed" v-if="msgInfo.status == $enums.MESSAGE_STATUS.READED">已读</text>
<text class="chat-unread" v-else>未读</text> <text class="chat-unread" v-else>未读</text>

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

@ -1,119 +1,122 @@
<template> <template>
<view class="im-nav-bar"> <view class="im-nav-bar">
<!-- #ifndef H5 --> <!-- #ifdef APP-PLUS -->
<view style="height: var(--status-bar-height)"></view> <view style="height: var(--status-bar-height)"></view>
<!-- #endif --> <!-- #endif -->
<view class="im-nav-bar-content"> <view class="im-nav-bar-content">
<view class="back" @click="handleBackClick" v-if="back"> <!-- #ifndef MP-WEIXIN -->
<uni-icons type="back" :size="iconFontSize"></uni-icons> <view class="back" @click="handleBackClick" v-if="back">
</view> <uni-icons type="back" :size="iconFontSize"></uni-icons>
<view class="title" v-if="title"> </view>
<slot></slot> <!-- #endif -->
</view> <view class="title" v-if="title">
<view class="btn"> <slot></slot>
<uni-icons class="btn-item" v-if="search" type="search" :size="iconFontSize" </view>
@click="$emit('search')"></uni-icons> <view class="btn">
<uni-icons class="btn-item" v-if="add" type="plusempty" :size="iconFontSize" @click="$emit('add')"></uni-icons> <uni-icons class="btn-item" v-if="search" type="search" :size="iconFontSize"
<uni-icons class="btn-item" v-if="more" type="more-filled" :size="iconFontSize" @click="$emit('search')"></uni-icons>
@click="$emit('more')"></uni-icons> <uni-icons class="btn-item" v-if="add" type="plusempty" :size="iconFontSize"
</view> @click="$emit('add')"></uni-icons>
</view> <uni-icons class="btn-item" v-if="more" type="more-filled" :size="iconFontSize"
</view> @click="$emit('more')"></uni-icons>
</view>
</view>
</view>
</template> </template>
<script> <script>
export default { export default {
name: "nav-bar", name: "nav-bar",
props: { props: {
back: { back: {
type: Boolean, type: Boolean,
default: false default: false
}, },
title: { title: {
type: Boolean, type: Boolean,
default: true default: true
}, },
search: { search: {
type: Boolean, type: Boolean,
default: false default: false
}, },
add: { add: {
type: Boolean, type: Boolean,
default: false default: false
}, },
more: { more: {
type: Boolean, type: Boolean,
default: false default: false
}, },
iconFontSize: { iconFontSize: {
type: Number, type: Number,
default: 24 default: 24
} }
}, },
data() { data() {
return {} return {}
}, },
computed: { computed: {
height() { height() {
} }
}, },
methods: { methods: {
handleBackClick() { handleBackClick() {
uni.navigateBack({ uni.navigateBack({
delta: 1 delta: 1
}) })
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.im-nav-bar { .im-nav-bar {
background-color: #fff; background-color: #fff;
//background-color: $im-bg; //background-color: $im-bg;
position: fixed; position: fixed;
top: 0; top: 0;
width: 100%; width: 100%;
color: $im-text-color; color: $im-text-color;
border-bottom: 1px solid $im-border-light; border-bottom: 1px solid $im-border-light;
font-size: $im-font-size-large; font-size: $im-font-size-large;
z-index: 99; z-index: 99;
.im-nav-bar-content { .im-nav-bar-content {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
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;
left: 0; left: 0;
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 12px; padding: 12px;
font-size: 22px; font-size: 22px;
box-sizing: border-box; box-sizing: border-box;
} }
.btn { .btn {
position: absolute; position: absolute;
right: 0; right: 0;
height: 100%; height: 100%;
display: flex; display: flex;
padding: 12px; padding: 12px;
align-items: center; align-items: center;
box-sizing: border-box; box-sizing: border-box;
.btn-item { .btn-item {
margin-left: 8px; margin-left: 8px;
} }
} }
} }
} }
</style> </style>

10
im-uniapp/pages.json

@ -30,7 +30,9 @@
{ {
"path": "pages/chat/chat-box", "path": "pages/chat/chat-box",
"style": { "style": {
"navigationStyle": "custom", "mp-weixin": {
"disableScroll": true
},
"app-plus": { "app-plus": {
// adjustPanadjustResize=webview+ // adjustPanadjustResize=webview+
"softinputMode": "adjustResize" "softinputMode": "adjustResize"
@ -67,7 +69,13 @@
], ],
"globalStyle": { "globalStyle": {
"navigationBarTitleText": "盒子IM", "navigationBarTitleText": "盒子IM",
"navigationBarTextStyle": "black",
/* #ifndef MP-WEIXIN */
"navigationStyle": "custom", "navigationStyle": "custom",
/* #endif */
/* #ifdef MP-WEIXIN */
"navigationStyle": "default",
/* #endif */
"navigationBarBackgroundColor": "#f7f7f7", "navigationBarBackgroundColor": "#f7f7f7",
"backgroundColor": "#f7f7f7" "backgroundColor": "#f7f7f7"
}, },

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

@ -50,52 +50,55 @@
</view> </view>
</view> </view>
<view class="chat-tab-bar"> <view class="chat-tab-bar">
<view v-if="chatTabBox == 'tools'" class="chat-tools" :style="{height: keyboardHeight+'px'}"> <scroll-view v-if="chatTabBox == 'tools'" class="chat-tools" :style="{height: keyboardHeight+'px'}">
<view class="chat-tools-item"> <view class="chat-tools-list">
<file-upload ref="fileUpload" :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess" <view class="chat-tools-item">
:onError="onUploadFileFail"> <file-upload ref="fileUpload" :onBefore="onUploadFileBefore" :onSuccess="onUploadFileSuccess"
<view class="tool-icon iconfont icon-folder"></view> :onError="onUploadFileFail">
</file-upload> <view class="tool-icon iconfont icon-folder"></view>
<view class="tool-name">文件</view> </file-upload>
</view> <view class="tool-name">文件</view>
<view class="chat-tools-item"> </view>
<image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore" <view class="chat-tools-item">
:onSuccess="onUploadImageSuccess" :onError="onUploadImageFail"> <image-upload :maxCount="9" sourceType="album" :onBefore="onUploadImageBefore"
<view class="tool-icon iconfont icon-picture"></view> :onSuccess="onUploadImageSuccess" :onError="onUploadImageFail">
</image-upload> <view class="tool-icon iconfont icon-picture"></view>
<view class="tool-name">相册</view> </image-upload>
</view> <view class="tool-name">相册</view>
<view class="chat-tools-item"> </view>
<image-upload sourceType="camera" :onBefore="onUploadImageBefore" :onSuccess="onUploadImageSuccess" <view class="chat-tools-item">
:onError="onUploadImageFail"> <image-upload sourceType="camera" :onBefore="onUploadImageBefore"
<view class="tool-icon iconfont icon-camera"></view> :onSuccess="onUploadImageSuccess" :onError="onUploadImageFail">
</image-upload> <view class="tool-icon iconfont icon-camera"></view>
<view class="tool-name">拍摄</view> </image-upload>
</view> <view class="tool-name">拍摄</view>
<view class="chat-tools-item" @click="onRecorderInput()"> </view>
<view class="tool-icon iconfont icon-microphone"></view> <view class="chat-tools-item" @click="onRecorderInput()">
<view class="tool-name">语音消息</view> <view class="tool-icon iconfont icon-microphone"></view>
</view> <view class="tool-name">语音消息</view>
<view v-if="chat.type == 'GROUP' && memberSize<=500" class="chat-tools-item" @click="switchReceipt()"> </view>
<view class="tool-icon iconfont icon-receipt" :class="isReceipt ? 'active' : ''"></view> <view v-if="chat.type == 'GROUP' && memberSize<=500" class="chat-tools-item"
<view class="tool-name">回执消息</view> @click="switchReceipt()">
</view> <view class="tool-icon iconfont icon-receipt" :class="isReceipt ? 'active' : ''"></view>
<!-- #ifndef MP-WEIXIN --> <view class="tool-name">回执消息</view>
<!-- 音视频不支持小程序 --> </view>
<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVideo()"> <!-- #ifndef MP-WEIXIN -->
<view class="tool-icon iconfont icon-video"></view> <!-- 音视频不支持小程序 -->
<view class="tool-name">视频通话</view> <view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVideo()">
</view> <view class="tool-icon iconfont icon-video"></view>
<view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVoice()"> <view class="tool-name">视频通话</view>
<view class="tool-icon iconfont icon-call"></view> </view>
<view class="tool-name">语音通话</view> <view v-if="chat.type == 'PRIVATE'" class="chat-tools-item" @click="onPriviteVoice()">
</view> <view class="tool-icon iconfont icon-call"></view>
<view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="onGroupVideo()"> <view class="tool-name">语音通话</view>
<view class="tool-icon iconfont icon-call"></view> </view>
<view class="tool-name">语音通话</view> <view v-if="chat.type == 'GROUP'" class="chat-tools-item" @click="onGroupVideo()">
<view class="tool-icon iconfont icon-call"></view>
<view class="tool-name">语音通话</view>
</view>
<!-- #endif -->
</view> </view>
<!-- #endif --> </scroll-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"
:style="{height: keyboardHeight+'px'}"> :style="{height: keyboardHeight+'px'}">
<view class="emotion-item-list"> <view class="emotion-item-list">
@ -133,6 +136,7 @@ export default {
showRecord: false, showRecord: false,
chatMainHeight: 800, // chatMainHeight: 800, //
keyboardHeight: 290, // keyboardHeight: 290, //
screenHeight: 1000, //
windowHeight: 1000, // windowHeight: 1000, //
initHeight: 1000, // h5 initHeight: 1000, // h5
atUserIds: [], atUserIds: [],
@ -393,10 +397,12 @@ export default {
this.switchChatTabBox('tools') this.switchChatTabBox('tools')
}, },
switchChatTabBox(chatTabBox) { switchChatTabBox(chatTabBox) {
this.chatTabBox = chatTabBox; if (this.chatTabBox != chatTabBox) {
this.reCalChatMainHeight(); this.chatTabBox = chatTabBox;
if (chatTabBox != 'tools' && this.$refs.fileUpload) { if (chatTabBox != 'tools' && this.$refs.fileUpload) {
this.$refs.fileUpload.hide() this.$refs.fileUpload.hide()
}
setTimeout(() => this.reCalChatMainHeight(), 30);
} }
}, },
selectEmoji(emoText) { selectEmoji(emoText) {
@ -815,39 +821,42 @@ export default {
} }
}, },
reCalChatMainHeight() { reCalChatMainHeight() {
setTimeout(() => { let sysInfo = uni.getSystemInfoSync();
let h = this.windowHeight; let h = this.windowHeight;
// //
h -= 50; h -= 50;
// //
if (this.isShowKeyBoard || this.chatTabBox != 'none') { if (this.isShowKeyBoard || this.chatTabBox != 'none') {
h -= this.keyboardHeight; // ios app
this.scrollToBottom(); // #ifdef APP-PLUS
} if (sysInfo.platform == 'ios') {
// #ifndef H5 h += this.screenHeight - this.windowHeight;
// h5
h -= uni.getSystemInfoSync().statusBarHeight;
// #endif
this.chatMainHeight = h;
if (this.isShowKeyBoard || this.chatTabBox != 'none') {
this.scrollToBottom();
}
// ios
// #ifdef H5
if (uni.getSystemInfoSync().platform == 'ios') {
//
const delays = [50, 100, 500];
delays.forEach((delay) => {
setTimeout(() => {
uni.pageScrollTo({
scrollTop: 0,
duration: 10
});
}, delay);
})
} }
// #endif // #endif
}, 30) h -= this.keyboardHeight;
this.scrollToBottom();
}
// APP
// #ifdef APP-PLUS
h -= sysInfo.statusBarHeight;
// #endif
this.chatMainHeight = h;
// #ifndef APP
// ios
if (uni.getSystemInfoSync().platform == 'ios') {
//
const delays = [50, 100, 500];
delays.forEach((delay) => {
setTimeout(() => {
uni.pageScrollTo({
scrollTop: 0,
duration: 10
});
}, delay);
})
}
// #endif
}, },
listenKeyBoard() { listenKeyBoard() {
// #ifdef H5 // #ifdef H5
@ -889,7 +898,7 @@ export default {
if (this.isShowKeyBoard) { if (this.isShowKeyBoard) {
this.keyboardHeight = res.height; // this.keyboardHeight = res.height; //
} }
this.reCalChatMainHeight(); setTimeout(() => this.reCalChatMainHeight(), 30);
}, },
resizeListener() { resizeListener() {
let keyboardHeight = this.initHeight - window.innerHeight; let keyboardHeight = this.initHeight - window.innerHeight;
@ -902,15 +911,15 @@ export default {
if (this.isShowKeyBoard) { if (this.isShowKeyBoard) {
this.keyboardHeight = keyboardHeight; this.keyboardHeight = keyboardHeight;
} }
this.reCalChatMainHeight(); setTimeout(() => this.reCalChatMainHeight(), 30);
}, },
focusInListener() { focusInListener() {
this.isShowKeyBoard = true; this.isShowKeyBoard = true;
this.reCalChatMainHeight(); setTimeout(() => this.reCalChatMainHeight(), 30);
}, },
focusOutListener() { focusOutListener() {
this.isShowKeyBoard = false; this.isShowKeyBoard = false;
this.reCalChatMainHeight(); setTimeout(() => this.reCalChatMainHeight(), 30);
}, },
showBannedTip() { showBannedTip() {
let msgInfo = { let msgInfo = {
@ -1082,7 +1091,11 @@ export default {
// //
this.listenKeyBoard(); this.listenKeyBoard();
// //
this.windowHeight = uni.getSystemInfoSync().windowHeight;
this.screenHeight = uni.getSystemInfoSync().screenHeight;
this.reCalChatMainHeight();
this.$nextTick(() => { this.$nextTick(() => {
// windowHeight
this.windowHeight = uni.getSystemInfoSync().windowHeight; this.windowHeight = uni.getSystemInfoSync().windowHeight;
this.reCalChatMainHeight(); this.reCalChatMainHeight();
this.scrollToBottom(); this.scrollToBottom();
@ -1132,10 +1145,10 @@ export default {
} }
.chat-main-box { .chat-main-box {
// #ifdef H5 // #ifndef APP-PLUS
top: $im-nav-bar-height; top: $im-nav-bar-height;
// #endif // #endif
// #ifndef H5 // #ifdef APP-PLUS
top: calc($im-nav-bar-height + var(--status-bar-height)); top: calc($im-nav-bar-height + var(--status-bar-height));
// #endif // #endif
position: fixed; position: fixed;
@ -1206,7 +1219,7 @@ export default {
border-top: $im-border solid 1px; border-top: $im-border solid 1px;
background-color: $im-bg; background-color: $im-bg;
min-height: 80rpx; min-height: 80rpx;
margin-bottom: 14rpx; padding-bottom: 14rpx;
.iconfont { .iconfont {
font-size: 60rpx; font-size: 60rpx;
@ -1250,44 +1263,45 @@ export default {
background-color: $im-bg; background-color: $im-bg;
.chat-tools { .chat-tools {
display: flex;
flex-wrap: wrap;
align-items: top;
height: 310px;
padding: 40rpx; padding: 40rpx;
box-sizing: border-box; box-sizing: border-box;
.chat-tools-item { .chat-tools-list {
width: 25%;
padding: 16rpx;
box-sizing: border-box;
display: flex; display: flex;
flex-direction: column; flex-wrap: wrap;
align-items: center; align-content: center;
.tool-icon { .chat-tools-item {
padding: 26rpx; width: 25%;
font-size: 54rpx; padding: 16rpx;
border-radius: 20%; box-sizing: border-box;
background-color: white; display: flex;
color: $icon-color; flex-direction: column;
align-items: center;
.tool-icon {
padding: 26rpx;
font-size: 54rpx;
border-radius: 20%;
background-color: white;
color: $icon-color;
&:active { &:active {
background-color: $im-bg-active; background-color: $im-bg-active;
}
} }
}
.tool-name { .tool-name {
height: 60rpx; height: 60rpx;
line-height: 60rpx; line-height: 60rpx;
font-size: 28rpx; font-size: 28rpx;
}
} }
} }
} }
.chat-emotion { .chat-emotion {
height: 310px; padding: 40rpx;
padding: 20rpx;
box-sizing: border-box; box-sizing: border-box;
.emotion-item-list { .emotion-item-list {

Loading…
Cancel
Save