x***@126.com
x***@126.com
  • 发布:2024-04-30 21:34
  • 更新:2024-05-06 22:14
  • 阅读:88

原创uniapp+vue3+uni-ui聊天室|uni-app+vue3仿微信app模板

分类:uni-app

原创研发uniapp+vue3+pinia2+uv-ui+vite4.x跨端仿微信app聊天Uniapp-Wechat。支持编译到H5+小程序端+App端。实现编辑框多行自适应高度消息+emoj混合、长按仿微信语音面板、图片/视频预览、红包/朋友圈等功能。

https://ask.dcloud.net.cn/article/40928

编译h5+小程序+APP端效果

img

uni-vue3-wechat项目使用HbuilderX4.0.8开发工具,采用vue3 setup语法规范编码。

img

使用技术

  • 开发工具:HbuilderX 4.0.8
  • 技术框架:Uniapp+Vue3+Pinia2+Vite4.x
  • UI组件库:uni-ui+uv-ui
  • 弹框组件:uv3-popup(uniapp+vue3多端自定义弹框组件)
  • 自定义组件:uv3-navbar+uv3-tabbar组件
  • 缓存服务:pinia-plugin-unistorage
  • 编译支持:H5+小程序+APP端

img

img

img

img

项目结构图

img

main.js配置

/**  
 * 入口文件 main.js  
*/  

import { createSSRApp } from 'vue'  
import App from './App'  

// 引入pinia状态管理  
import pinia from '@/pinia'  

export function createApp() {  
    const app = createSSRApp(App)  
    app.use(pinia)  
    return {  
        app,  
        pinia  
    }  
}

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

img

在web端则是以750px像素布局。

img

App.vue配置

<script setup>  
    import { provide } from 'vue'  
    import { onLaunch, onShow, onHide, onPageNotFound } from '@dcloudio/uni-app'  

    onLaunch(() => {  
        console.log('App Launch')  

        uni.hideTabBar()  
        loadSystemInfo()  
    })  

    onShow(() => {  
        console.log('App Show')  
    })  

    onHide(() => {  
        console.log('App Hide')  
    })  

    onPageNotFound((e) => {  
        console.warn('Route Error:', `${e.path}`)  
    })  

    // 获取系统设备信息  
    const loadSystemInfo = () => {  
        uni.getSystemInfo({  
            success: (e) => {  
                // 获取手机状态栏高度  
                let statusBar = e.statusBarHeight  
                let customBar  

                // #ifndef MP  
                customBar = statusBar + (e.platform == 'android' ? 50 : 45)  
                // #endif  

                // #ifdef MP-WEIXIN  
                // 获取按钮的布局位置信息  
                let menu = wx.getMenuButtonBoundingClientRect()  
                // 导航栏高度 = 下距离 + 上距离 - 状态栏高度  
                customBar = menu.bottom + menu.top - statusBar  
                // #endif  

                // #ifdef MP-ALIPAY  
                customBar = statusBar + e.titleBarHeight  
                // #endif  

                // 由于globalData在vue3 setup存在兼容性问题,改为provide/inject替代方案  
                provide('globalData', {  
                    statusBarH: statusBar,  
                    customBarH: customBar,  
                    screenWidth: e.screenWidth,  
                    screenHeight: e.screenHeight,  
                    platform: e.platform  
                })  
            }  
        })  
    }  
</script>  

<style>  
    /* #ifndef APP-NVUE */  
    @import 'static/fonts/iconfont.css';  
    /* #endif */  
</style>  
<style lang="scss">  
    @import 'styles/reset.scss';  
    @import 'styles/layout.scss';  
</style>

公共布局模板

项目整体分为顶部区域+内容区+底部区域三个大的模块。

img

img

<!-- 公共布局模板 -->  

<!-- #ifdef MP-WEIXIN -->  
<script>  
    export default {  
        /**  
         * 解决小程序class、id问题  
         * manifest.json中配置mergeVirtualHostAttributes: true, 在微信小程序平台不生效,组件外部传入的class没有挂到组件根节点上,在组件中增加options: { virtualHost: true }  
         * https://github.com/dcloudio/uni-ui/issues/753  
         */  
        options: { virtualHost: true }  
    }  
</script>  
<!-- #endif -->  

<script setup>  
    const props = defineProps({  
        // 是否显示自定义tabbar  
        showTabBar: { type: [Boolean, String], default: false },  
    })  
</script>  

<template>  
    <view class="uv3__container flexbox flex-col flex1">  
        <!-- 顶部插槽 -->  
        <slot name="header" />  

        <!-- 内容区 -->  
        <view class="uv3__scrollview flex1">  
            <slot />  
        </view>  

        <!-- 底部插槽 -->  
        <slot name="footer" />  

        <!-- tabbar栏 -->  
        <uv3-tabbar v-if="showTabBar" hideTabBar fixed />  
    </view>  
</template>

uniapp+vue3实现微信九宫格图像

img

<script setup>  
    import { onMounted, ref, computed, watch, getCurrentInstance } from 'vue'  

    const props = defineProps({  
        // 图像组  
        avatar: { type: Array, default: null },  
    })  

    const instance = getCurrentInstance()  

    const uuid = computed(() => Math.floor(Math.random() * 10000))  
    const avatarPainterId = ref('canvasid' + uuid.value)  

    const createAvatar = () => {  
        const ctx = uni.createCanvasContext(avatarPainterId.value, instance)  
        // 计算图像在画布上的坐标  
        const avatarSize = 12  
        const gap = 2  
        for(let i = 0, len = props.avatar.length; i < len; i++) {  
            const row = Math.floor(i / 3)  
            const col = i % 3  
            const x = col * (avatarSize + gap)  
            const y = row * (avatarSize + gap)  

            ctx.drawImage(props.avatar[i], x, y, avatarSize, avatarSize)  
        }  
        ctx.draw(false, () => {  
            // 输出临时图片  
            /* uni.canvasToTempFilePath({  
                canvasId: avatarPainterId.value,  
                success: (res) => {  
                    console.log(res.tempFilePath)  
                }  
            }) */  
        })  
    }  

    onMounted(() => {  
        createAvatar()  
    })  

    watch(() => props.avatar, () => {  
        createAvatar()  
    })  
</script>  

<template>  
    <template v-if="avatar.length > 1">  
        <view class="uv3__avatarPainter">  
            <canvas :canvas-id="avatarPainterId" class="uv3__avatarPainter-canvas"></canvas>  
        </view>  
    </template>  
    <template v-else>  
        <image class="uv3__avatarOne" :src="avatar[0]" />  
    </template>  
</template>  

<style lang="scss" scoped>  
    .uv3__avatarPainter {background-color: #eee; border-radius: 5px; overflow: hidden; padding: 2px; height: 44px; width: 44px;}  
    .uv3__avatarPainter-canvas {height: 100%; width: 100%;}  
    .uv3__avatarOne {border-radius: 5px; height: 44px; width: 44px;}  
</style>

img

img

img

项目中顶部导航条、底部菜单栏、各种弹窗功能均是使用自定义组件实现功能。

uniapp+vue3聊天功能

img

img

img

<view v-if="voicePanelEnable" class="uv3__voicepanel-popup">  
    <view class="uv3__voicepanel-body flexbox flex-col">  
        <!-- 取消发送+语音转文字 -->  
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-transfer">  
            <!-- 提示动效 -->  
            <view class="animtips flexbox" :class="voiceType == 2 ? 'left' : voiceType == 3 ? 'right' : null"><Waves :lines="[2, 3].includes(voiceType) ? 10 : 20" /></view>  
            <!-- 操作项 -->  
            <view class="icobtns flexbox">  
                <view class="vbtn cancel flexbox flex-col" :class="{'hover': voiceType == 2}" @click="handleVoiceCancel"><text class="vicon uv3-icon uv3-icon-close"></text></view>  
                <view class="vbtn word flexbox flex-col" :class="{'hover': voiceType == 3}"><text class="vicon uv3-icon uv3-icon-word"></text></view>  
            </view>  
        </view>  

        <!-- 识别结果状态 -->  
        <view v-if="voiceToTransfer" class="uv3__voicepanel-transfer result fail">  
            <!-- 提示动效 -->  
            <view class="animtips flexbox"><uni-icons type="info-filled" color="#fff" size="20"></uni-icons><text class="c-fff">未识别到文字</text></view>  
            <view class="icobtns flexbox">  
                <view class="vbtn cancel flexbox flex-col" @click="handleVoiceCancel"><text class="vicon uv3-icon uv3-icon-chexiao"></text>取消</view>  
                <view class="vbtn word flexbox flex-col"><text class="vicon uv3-icon uv3-icon-audio"></text>发送原语音</view>  
                <view class="vbtn check flexbox flex-col"><text class="vicon uv3-icon uv3-icon-duigou"></text></view>  
            </view>  
        </view>  

        <!-- 背景语音图 -->  
        <view class="uv3__voicepanel-cover">  
            <image v-if="!voiceToTransfer" src="/static/voice_bg.webp" :webp="true" mode="widthFix" style="width: 100%;" />  
        </view>  
        <!-- 提示文字 -->  
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-tooltip">{{voiceTypeMap[voiceType]}}</view>  
        <!-- 背景图标 -->  
        <view v-if="!voiceToTransfer" class="uv3__voicepanel-fixico"><text class="uv3-icon uv3-icon-audio fs-50"></text></view>  
    </view>  
</view>

Okay,综上就是uni-app+vue3实战开发微信app聊天项目的一些知识分享。

作者:xiaoyan2015
链接: https://juejin.cn/post/7363121890791899170
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 关注 分享

要回复文章请先登录注册

x***@126.com

x***@126.com (作者)

该项目已经同步到工坊,有需要可以去看看哈~
[https://gf.bilibili.com/item/detail/1105801011](https://gf.bilibili.com/item/detail/1105801011)
2024-05-06 22:14