diff --git a/components/message/chat/chat-layout.vue b/components/message/chat/chat-layout.vue index 832bed6..3262f05 100644 --- a/components/message/chat/chat-layout.vue +++ b/components/message/chat/chat-layout.vue @@ -57,8 +57,9 @@ + :src="`/static/image/phone-message/${phone}/chat-left.png`" @click="chooseImage()"> + @@ -91,7 +92,7 @@ @click="sendMessage"> + src="/static/image/phone-message/huawei/chat-add.png" @click="chooseImage()"> \ No newline at end of file diff --git a/components/message/chat/chat-list.vue b/components/message/chat/chat-list.vue index 6ead8b4..c1b6806 100644 --- a/components/message/chat/chat-list.vue +++ b/components/message/chat/chat-list.vue @@ -34,24 +34,45 @@ 送达 + - - + + + + + + + + {{ formatHuaweiBottomTime(message.time) }} - 已送达 + {{ phone == 'vivo' ? '已发送' : '已送达' }} @@ -68,6 +89,7 @@ const handleImageClick = (message) => { if (!src) return; const allImages = []; + const allTimes = []; let clickIndex = 0; displayList.value.forEach(msg => { @@ -78,12 +100,13 @@ const handleImageClick = (message) => { clickIndex = allImages.length; } allImages.push(imgSrc); + allTimes.push(msg.time); } } }); - if (props.phone === 'oppo') { - emit('previewImage', { images: allImages, index: clickIndex }); + if (props.phone === 'oppo' || props.phone === 'mi') { + emit('previewImage', { images: allImages, index: clickIndex, times: allTimes }); } else { uni.previewImage({ urls: allImages, current: clickIndex }); } @@ -136,9 +159,9 @@ let sortItemRects = [] watch(() => props.sortMode, (val) => { if (val) { let list = props.messageList; - if (props.phone !== 'oppo') { - list = list.filter(msg => !isImageMsg(msg)); - } + // if (props.phone !== 'oppo') { + // list = list.filter(msg => !isImageMsg(msg)); + // } localSortList.value = list.map(item => ({ ...item })) } else { dragIndex.value = -1 @@ -154,9 +177,9 @@ const displayList = computed(() => { if (props.sortMode) return localSortList.value let list = props.messageList; - if (props.phone !== 'oppo') { - list = list.filter(msg => !isImageMsg(msg)); - } + // if (props.phone !== 'oppo') { + // list = list.filter(msg => !isImageMsg(msg)); + // } return list; }) @@ -200,12 +223,8 @@ const shouldApplyTailRight = (index) => { // 条件 c: 下一条消息 isMe == false (也就是被打断了) if (!nextMsg.isMe) return true; - // 条件 a: 下一条消息间隔三分钟以上 (180000 毫秒) - 时间分割线导致当前段落结束 - const currentMsgTime = new Date(currentMsg.time.replace(/-/g, '/')).getTime(); - const nextMsgTime = new Date(nextMsg.time.replace(/-/g, '/')).getTime(); - if (!isNaN(currentMsgTime) && !isNaN(nextMsgTime) && (nextMsgTime - currentMsgTime > 180000)) { - return true; - } + // 如果下一条消息上方显示了时间,则当前消息就是这一段的最后一条,应该有尾巴! + if (shouldShowTime(index + 1)) return true; // 其他情况(连绵不断的连发,中间没超时间也没被对方打断),则隐藏中间环节气泡尾巴 return false; @@ -224,21 +243,11 @@ const shouldApplyTailLeft = (index) => { // 条件 c: 下一条消息 isMe == true if (nextMsg.isMe) return true; - // 条件 a: 下一条消息间隔三分钟以上 (180000 毫秒) - const currentMsgTime = new Date(currentMsg.time.replace(/-/g, '/')).getTime(); - const nextMsgTime = new Date(nextMsg.time.replace(/-/g, '/')).getTime(); - if (!isNaN(currentMsgTime) && !isNaN(nextMsgTime) && (nextMsgTime - currentMsgTime > 180000)) { - return true; - } + // 如果下一条消息上方显示了时间,则当前消息就是这一段的最后一条,应该有尾巴! + if (shouldShowTime(index + 1)) return true; - // 条件 b: 这是最后一条 isMe == false 的消息 - for (let i = index + 1; i < displayList.value.length; i++) { - if (!displayList.value[i].isMe) { - return false; // 往后还有不是自己发的消息,所以当前并非最后一条 isMe==false - } - } - - return true; + // 否则说明后面还有相连的对方消息,不用加尾巴 + return false; } // 获取格式化后的聊天时间显示 @@ -392,9 +401,55 @@ const getImageSrc = (message) => { return ''; } +// 获取图片渲染模式 +const getImageMode = (message, phone) => { + if (phone === 'iphone') return 'widthFix'; + if (phone === 'huawei') { + const w = parseInt(message.imgWidth); + const h = parseInt(message.imgHeight); + if (!isNaN(w) && !isNaN(h)) { + if (h > w) return 'heightFix'; + return 'widthFix'; + } + return 'widthFix'; + } + return 'aspectFill'; +} + // 提取并应用图片的特定宽高 const getImageStyle = (message) => { if (message.imgWidth && message.imgHeight) { + if (props.phone === 'mi') { + const w = parseInt(message.imgWidth); + const h = parseInt(message.imgHeight); + if (!isNaN(w) && !isNaN(h)) { + if (h > w) { + return { width: '214rpx', height: '256rpx' }; + } else { + return { width: '256rpx', height: '214rpx' }; + } + } + } else if (props.phone === 'vivo') { + const w = parseInt(message.imgWidth); + const h = parseInt(message.imgHeight); + if (!isNaN(w) && !isNaN(h)) { + if (h > w) { + return { width: '284rpx', height: '400rpx' }; + } else { + return { width: '400rpx', height: '284rpx' }; + } + } + } else if (props.phone === 'huawei') { + const w = parseInt(message.imgWidth); + const h = parseInt(message.imgHeight); + if (!isNaN(w) && !isNaN(h)) { + if (h > w) { + return { height: '500rpx', 'max-height': '500rpx' }; + } else { + return { width: '500rpx', 'max-width': '500rpx' }; + } + } + } return { width: message.imgWidth, height: message.imgHeight @@ -550,7 +605,7 @@ const onSortTouchEnd = () => { background-color: transparent !important; padding: 0 !important; border: none !important; - border-radius: 16rpx !important; + // border-radius: 16rpx !important; overflow: hidden; } @@ -597,6 +652,85 @@ const onSortTouchEnd = () => { margin: 4rpx 30rpx 0; word-break: break-all; } + + .image-bubble { + border-radius: 0 !important; + margin-left: 10rpx; + } + + .image-wrap-left { + position: relative; + + &::before { + content: ""; + position: absolute; + z-index: 10; + top: 0; + left: 10px; + width: 17px; + height: 17px; + /* 使用径向渐变画出反向圆角:中心点在右下角,34rpx以内透明,以外纯白 */ + background: radial-gradient(circle at bottom right, transparent 16.5px, #FFFFFF 17px); + } + + + &::after { + content: ""; + position: absolute; + z-index: 10; + height: 100%; + width: 10px; + background-color: #FFFFFF !important; + left: 0px; + top: 0; + bottom: 0; + border-radius: 0 0 10px 0; + } + } + + .image-wrap-right { + position: relative; + + &::before { + content: ""; + position: absolute; + z-index: 10; + top: 0; + right: 10px; + width: 17px; + height: 17px; + /* 使用径向渐变画出反向圆角:中心点在右下角,34rpx以内透明,以外纯白 */ + background: radial-gradient(circle at bottom left, transparent 16.5px, #FFFFFF 17px); + } + + + &::after { + content: ""; + position: absolute; + z-index: 10; + height: 100%; + width: 10px; + background-color: #FFFFFF !important; + right: 0px; + top: 0; + bottom: 0; + border-radius: 0 0 0 10px; + } + } + + + .mask-left-bottom { + position: absolute; + left: 7px; + bottom: 0px; + } + + .mask-right-bottom { + position: absolute; + right: 7px; + bottom: 0px; + transform: scaleX(-1); + } } @@ -615,6 +749,14 @@ const onSortTouchEnd = () => { position: relative; } + .image-tail-left { + align-items: center; + + ::v-deep.image-bubble { + margin-right: 24rpx !important; + } + } + .tail-left::after { position: absolute; left: 18rpx; @@ -630,6 +772,23 @@ const onSortTouchEnd = () => { position: relative; } + .delivered { + display: flex; + flex-direction: column; + align-items: flex-end; + position: relative; + margin-bottom: 70rpx; + + .send-text { + margin-right: 32rpx; + font-weight: 400; + font-size: 20rpx; + color: #8B8B8B; + line-height: 20rpx; + margin-top: 12rpx; + } + } + .delivered::before { position: absolute; right: 18rpx; @@ -651,10 +810,28 @@ const onSortTouchEnd = () => { width: 28rpx; height: 36rpx; } + + .chat-image { + width: 516rpx; + max-width: 516rpx !important; + + } + + .chat-image-left { + border-radius: 0 34rpx 34rpx 0; + } + + .chat-image-right { + border-radius: 34rpx 0 0 34rpx; + } } // 小米样式 .mi-style { + .chat-image { + border-radius: 40rpx; + } + .top-text { text-align: center; font-size: 20rpx; @@ -888,6 +1065,10 @@ const onSortTouchEnd = () => { margin-top: 24rpx !important; } + .chat-image { + border-radius: 32rpx; + } + .time { color: #ACACAC; font-size: 24rpx; diff --git a/components/message/chat/image-preview.vue b/components/message/chat/image-preview.vue index d11af33..ea9fc8d 100644 --- a/components/message/chat/image-preview.vue +++ b/components/message/chat/image-preview.vue @@ -1,20 +1,51 @@