Vue3-ViteWchat:基于vue3.x+pinia2+element-plus仿微信web版聊天室

vite5.x-webchat:原创vite5+vue3+pinia2+elementPlus构建桌面web端聊天系统。

使用技术

  • 开发工具:vscode
  • 技术框架:vite5.2+vue3.4+vue-router4.3+pinia2
  • UI组件库:element-plus^2.7.5 (饿了么网页端vue3组件库)
  • 状态管理:pinia^2.1.7
  • 地图插件:@amap/amap-jsapi-loader(高德地图组件)
  • 视频滑动:swiper^11.1.4
  • 样式编译:sass^1.77.4
  • 构建工具:vite^5.2.0

项目目录结构

使用vite5.x搭建项目模板,采用vue3 setup语法编码。

vite-webchat包含了聊天、通讯录、朋友圈、短视频、我的等功能模块。支持收缩侧边栏、背景壁纸换肤、锁屏、最大化等功能。

目前该项目已经正式发布到我的原创作品集,感兴趣的话,可以去看一看。
gf.bilibili.com/item/detail/110622...

入口main.js配置

import { createApp } from 'vue'
import './style.scss'
import App from './App.vue'

// 引入组件库
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import VEPlus from 've-plus'
import 've-plus/dist/ve-plus.css'

// 引入路由/状态管理
import Router from './router'
import Pinia from './pinia'

const app = createApp(App)

app
.use(ElementPlus)
.use(VEPlus)
.use(Router)
.use(Pinia)
.mount('#app')

主布局模板

<template>
  <div class="vu__container" :style="{'--themeSkin': appstate.config.skin}">
    <div class="vu__layout">
      <div class="vu__layout-body">
        <!-- 菜单栏 -->
        <slot v-if="!route?.meta?.hideMenuBar" name="menubar">
          <MenuBar />
        </slot>

        <!-- 侧边栏 -->
        <div v-if="route?.meta?.showSideBar" class="vu__layout-sidebar" :class="{'hidden': appstate.config.collapsed}">
          <aside class="vu__layout-sidebar__body flexbox flex-col">
            <slot name="sidebar">
              <SideBar />
            </slot>

            <!-- 折叠按钮 -->
            <Collapse />
          </aside>
        </div>

        <!-- 主内容区 -->
        <div class="vu__layout-main flex1 flexbox flex-col">
          <Winbtn v-if="!route?.meta?.hideWinBar" />
          <router-view v-slot="{ Component, route }">
            <keep-alive>
              <component :is="Component" :key="route.path" />
            </keep-alive>
          </router-view>
        </div>
      </div>
    </div>
  </div>
</template>

vue3路由配置

/**
 * 路由管理Router
 * @author andy
 */

import { createRouter, createWebHashHistory } from 'vue-router'
import { authState } from '@/pinia/modules/auth'

import Layout from '@/layouts/index.vue'

// 批量导入路由
const modules = import.meta.glob('./modules/*.js', { eager: true })
const patchRouters = Object.keys(modules).map(key => modules[key].default).flat()

/**
 * meta配置
 * @param meta.requireAuth 需登录验证页面
 * @param meta.hideWinBar 隐藏右上角按钮组
 * @param meta.hideMenuBar 隐藏菜单栏
 * @param meta.showSideBar 显示侧边栏
 * @param meta.canGoBack 是否可回退上一页
 */
const routes = [
  ...patchRouters,
  // 错误模块
  {
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    component: Layout,
    meta: {
      title: '404error',
      hideMenuBar: true,
      hideWinBar: true,
    },
    children: [
      {
        path: '404',
        component: () => import('@/views/error/404.vue'),
      }
    ]
  },
]

const router = createRouter({
  history: createWebHashHistory(),
  routes,
})

// 全局路由钩子拦截
router.beforeEach((to, from) => {
  const authstate = authState()
  // 登录验证
  if(to?.meta?.requireAuth && !authstate.authorization) {
    console.log('你还未登录!')
    return {
      path: '/login'
    }
  }
})

router.afterEach((to, from) => {
  // 阻止浏览器回退
  if(to?.meta?.canGoBack == false && from.path != null) {
    history.pushState(history.state, '', document.URL)
  }
})

vue3短视频模板

<!-- 短视频模块 -->
<div class="vu__video-container">
    <!-- tabs操作栏 -->
    <div class="vu__video-tabswrap flexbox">
        <el-tabs v-model="activeName" class="vu__video-tabs">
            <el-tab-pane label="关注" name="attention" />
            <el-tab-pane label="推荐" name="recommend" />
        </el-tabs>
    </div>
    <swiper-container
        class="vu__swiper"
        direction="vertical"
        :speed="150"
        :grabCursor="true"
        :mousewheel="{invert: true}"
        @swiperslidechange="onSlideChange"
    >
        <swiper-slide v-for="(item, index) in videoList" :key="index">
            <!-- 视频层 -->
            <video
                class="vu__player"
                :id="'vuplayer-' + index"
                :src="item.src"
                :poster="item.poster"
                loop
                preload="auto"
                :autoplay="index == currentVideo"
                webkit-playsinline="true" 
                x5-video-player-type="h5-page"
                x5-video-player-fullscreen="true"
                playsinline
                @click="handleVideoClicked"
            >
            </video>
            <div v-if="!isPlaying" class="vu__player-btn" @click="handleVideoClicked"></div>

            <!-- 右侧操作栏 -->
            <div class="vu__video-toolbar">
                ...
            </div>

            <!-- 底部信息区域 -->
            <div class="vu__video-footinfo flexbox flex-col">
                <div class="name">@{{item.author}}</div>
                <div class="content">{{item.desc}}</div>
            </div>
        </swiper-slide>
    </swiper-container>
    <!-- ///底部进度条 -->
    <el-slider class="vu__video-progressbar" v-model="progressBar" @input="handleSlider" @change="handlePlay" />
    <div v-if="isDraging" class="vu__video-duration">{{videoTime}} / {{videoDuration}}</div>
</div>

vue3聊天模板

<template>
  <!-- 顶部导航 -->
  ...

  <!-- 内容区 -->
  <div class="vu__layout-main__body">
    <Scrollbar ref="scrollRef" autohide gap="2">
      <!-- 渲染聊天内容 -->
      <div class="vu__chatview" @dragenter="handleDragEnter" @dragover="handleDragOver" @drop="handleDrop">
        ...
      </div>
    </Scrollbar>
  </div>

  <!-- 底部操作栏 -->
  <div class="vu__footview">
    <div class="vu__toolbar flexbox">
      ...
    </div>
    <div class="vu__editor">
      <Editor ref="editorRef" v-model="editorValue" @paste="handleEditorPaste" />
    </div>
    <div class="vu__submit">
      <button @click="handleSubmit">发送(S)</button>
    </div>
  </div>

  ...
</template>

// 拾取地图位置
let map = null
const handlePickMapLocation = () => {
  popoverChooseRef?.value?.hide()
  mapLocationVisible.value = true

  // 初始化地图
  AMapLoader.load({
    key: "af10789c28b6ef1929677bc5a2a3d443", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  }).then((AMap) => {
    // JS API 加载完成后获取AMap对象
    map = new AMap.Map("vu__mapcontainer", {
      viewMode: "3D", // 默认使用 2D 模式
      zoom: 10, // 初始化地图级别
      resizeEnable: true,
    })

    // 获取当前位置
    AMap.plugin('AMap.Geolocation', function() {
      var geolocation = new AMap.Geolocation({
        // 是否使用高精度定位,默认:true
        enableHighAccuracy: true,
        // 设置定位超时时间,默认:无穷大
        timeout: 10000,
        // 定位按钮的停靠位置的偏移量,默认:Pixel(10, 20)
        buttonOffset: new AMap.Pixel(10, 20),
        // 定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        zoomToAccuracy: true,
        // 定位按钮的排放位置, RB表示右下
        buttonPosition: 'RB'
      })

      map.addControl(geolocation)
      geolocation.getCurrentPosition(function(status, result){
        if(status == 'complete'){
          onComplete(result)
        }else{
          onError(result)
        }
      })
    })

    // 定位成功的回调函数
    function onComplete(data) {
      var str = ['定位成功']
      str.push('经度:' + data.position.getLng())
      str.push('纬度:' + data.position.getLat())
      if(data.accuracy){
        str.push('精度:' + data.accuracy + ' 米')
      }
      // 可以将获取到的经纬度信息进行使用
      console.log(str.join('<br>'))
    }

    // 定位失败的回调函数
    function onError(data) {
      console.log('定位失败:' + data.message)
    }
  }).catch((e) => {
    // 加载错误提示
    console.log('amapinfo', e)
  })
}

// 打开预览地图位置
const handleOpenMapLocation = (data) => {
  mapLocationVisible.value = true

  // 初始化地图
  AMapLoader.load({
    key: "af10789c28b6ef1929677bc5a2a3d443", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  }).then((AMap) => {
    // JS API 加载完成后获取AMap对象
    map = new AMap.Map("vu__mapcontainer", {
      viewMode: "3D", // 默认使用 2D 模式
      zoom: 13, // 初始化地图级别
      center: [data.longitude, data.latitude], // 初始化地图中心点位置
    })

    // 添加插件
    AMap.plugin(["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye"], function () {
      //异步同时加载多个插件
      map.addControl(new AMap.ToolBar()) // 缩放工具条
      map.addControl(new AMap.HawkEye()) // 显示缩略图
      map.addControl(new AMap.Scale()) // 显示当前地图中心的比例尺
    })

    mapPosition.value = [data.longitude, data.latitude]
    addMarker()

    // 实例化点标记
    function addMarker() {
      const marker = new AMap.Marker({
        icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
        position: mapPosition.value,
        offset: new AMap.Pixel(-26, -54),
      })
      marker.setMap(map)
      /* marker.setLabel({
        direction:'top',
        offset: new AMap.Pixel(0, -10),  //设置文本标注偏移量
        content: "<div class='info'>我是 marker 的 label 标签</div>", //设置文本标注内容
      }) */

      //鼠标点击marker弹出自定义的信息窗体
      marker.on('click', function () {
        infoWindow.open(map, marker.getPosition())
      })
      const infoWindow = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -60),
        content: `
          <div style="padding: 10px;">
            <p style="font-size: 14px;">${data.name}</p>
            <p style="color: #999; font-size: 12px;">${data.address}</p>
          </div>
        `
      })
    }
  }).catch((e) => {
    // 加载错误提示
    console.log('amapinfo', e)
  })
}
// 关闭预览地图位置
const handleCloseMapLocation = () => {
  map?.destroy()
  mapLocationVisible.value = false
}

博客:uniapp-weos:原创uniapp+vue3手机版后台OA管理系统(h5+小程序+App端...
博客:flutter-dylive:基于flutter3.x+getx短视频直播|Flutter3仿抖音app
博客:基于flutter3+getx+bitsdojo_window仿微信客户端|flutter聊天EXE

本作品采用《CC 协议》,转载必须注明作者和本文链接
本文为原创文章,未经作者允许不得转载,欢迎大家一起交流 QQ(282310962) wx(xy190310)
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
文章
64
粉丝
50
喜欢
107
收藏
57
排名:356
访问:2.7 万
私信
所有博文
博客标签
react
1
angular
1
react仿微信
2
react实战开发
2
react+redux
1
react网页聊天
2
angular仿微信
1
angular聊天室
1
angular+node聊天
1
h5仿微信
1
仿微信语音
1
仿微信界面
1
RN弹窗
1
react-native自定义弹窗
1
react-native弹窗
1
React Native
1
reactNative仿微信
1
RN仿微信聊天
1
ReactNative朋友圈
1
uniapp仿微信
1
uniapp聊天室
2
uniapp聊天App
1
uni-app+vue实例
1
uni-app即时通讯
1
uniapp直播
1
uni-app仿抖音
1
uniapp仿陌陌
1
uni-app小视频
1
taro仿微信
1
taro聊天室
1
taro仿微信界面
1
taro+react聊天APP
1
taro即时通讯
1
electron+vue
1
electron-vue仿微信
1
electron聊天
1
electron实例
1
flutter实例
1
flutter仿微信
1
flutter+dart聊天
1
flutter聊天室
1
flutter聊天界面
1
vue自定义弹窗
1
vue全局对话框
1
vue长按弹出框
1
vue右键弹层
1
nuxt对话框
1
vue仿微信弹窗
1
vue仿探探
1
vue仿Tinder
1
vue卡片堆叠
1
vue翻牌滑动
1
nuxt仿探探
1
nuxt聊天室
1
nuxt仿微信
1
nuxt即时聊天
1
vue+nuxt聊天实例
1
nuxt.js朋友圈
1
vue.js自定义对话框
1
vue pc端弹窗
1
vue.js桌面端模态框
1
vue弹窗组件
1
vue仿layer
1
vue.js自定义滚动条
1
vue虚拟滚动条
1
vue美化滚动条
1
vue仿饿了么滚动条
1
Vue-Scrollbar
1
react.js弹窗示例
1
react桌面端弹框
1
react.js自定义对话框
1
react pc自定义弹窗
1
react全局弹框
1
vue3.0自定义组件
2
vue3弹框
1
vue3.x对话框
1
vue3.0弹窗
1
vue3.0实例
1
vue3.0聊天室
1
vue3.0仿微信
2
vue3聊天模板
1
vue3+vant3实战开发
1
vue3.x案例
1
vue3聊天实例
1
vue3.0仿QQ
1
vue3.x实战聊天
1
vue3网页聊天
2
vue3.0仿抖音app
1
vue3短视频
1
vue3.x小视频
1
vue3.0直播实例
1
vue3+vite2+vant3实战
1
vue3跨端开发
1
electron仿QQ
1
electron打包
1
electron聊天室
1
electron仿微信
1
electron仿抖音
1
electron短视频
1
electron直播
1
vite2+electron12
1
vite2+vue3.x+swiper
1
vue3+vite.js+vant3
1
vue3后台系统
1
Electron管理系统
1
vite2+electron后台
1
electron12权限管理
1
electron桌面端后台
1
vue3桌面管理
1
vite2+electron13
1
electron仿mac桌面
1
electron桌面管理
1
vite2桌面应用
1
uniapp短视频
1
uniapp仿抖音
1
uni-app直播
1
uniapp后台
1
uni-app+uview后台系统
1
svelte.js实战开发
1
svelte3仿微信
1
svelte+svelteKit聊天室
1
svelte聊天实例
2
svelte朋友圈
1
svelte.js仿微信
1
svelte.js网页聊天
1
svelte-ui-admin
1
svelte-admin后台管理
1
svelte管理系统
1
tauri桌面应用
1
tauri+vue3
1
vite3+tauri
1
tauri聊天程序
1
tauri仿微信
1
vue3后台管理
1
vite.js管理系统
1
vue3+vite4
1
vite4+pinia
1
vue3+pinia2
1
vue3-chatgpt
2
vite-chatgpt
1
chatgpt-mobile
1
electron-chatgpt
1
electron+vite4+vue3
1
electron25-vue3
1
chatgpt-vite
1
uni-chatgpt
1
uniapp+vue3+pinia
4
vite+uniapp
1
chatgpt-uniapp
1
tauri-admin
1
tauri+rust+vue3
1
tauri后台管理
1
tauri-vite
1
tauri+vue3桌面端后台
1
react18 hooks
2
react18+arco
2
react18+zustand
1
react18-webchat
1
react18-admin
1
react-arco-admin
1
react-vite-admin
1
react18后台管理
1
electron-mateos
1
electron27+react18
1
electron-react-macos
1
electron桌面os
1
react-macos
1
uniapp+vue3直播
1
flutter3-chat
2
flutter3仿微信
2
flutter3聊天
2
flutter3+dart3
1
flutter3桌面端开发
1
flutter3-douyin
1
flutter3仿抖音
1
flutter3短视频
2
flutter3直播
1
flutter3-macos
1
flutter3-osx
2
flutter3桌面os
2
flutter3仿macOS
1
uniapp+vue3聊天
1
uniapp+vue3仿微信
1
uniapp+vue3聊天app
1
uniapp-vue3-wchat
1
uni-vue3-os
1
uniapp+vue3手机后台
1
uniapp-admin
1
uniapp+vue3仿ios桌面
1
uniapp+vite5后台管理
1
flutter3-osadmin
1
flutter3手机后台
1
vite-vue3-chat
1
vite-webchat
1
vue3-chat聊天
1
vite5仿微信
1
electron31+vue3聊天室
1
vite5+electron31仿微信
1
electron31-vite5-wechat聊天
1
electron31聊天exe
1
vue3+electron桌面聊天
1
vue3-webos
1
vue3-macos
1
vue3网页版os
1
vite-os
1
electron31-vue3-admin
1
vite5-electron31-admin
1
vue3+electron31后台系统
1
electron31+vite5桌面端后台
1
electron31轻量级后台
1
electron32-os
1
vue3+electron32桌面os
1
electron32-macos
1
electron32-winos
1
electron-osx
1
tauri2.0
2
tauri2+vue3仿微信
1
tauri2+vite.js聊天
1
tauri2.0+vue3客户端聊天
1
HarmonyOS
1
tauri2-admin
1
tauri2-vue3-admin
1
vue3+tauri2桌面后台
1
tauri2+vite后台系统
1
harmony-chat
1
鸿蒙仿微信
1
鸿蒙聊天app
1
uniapp+vue3酒店预订
1
vue3+uniapp预约酒店
1
uniapp酒店预订
1
uniapp仿携程
1
uniapp仿同程
1
vue3酒店预订
1
tauri2-os
1
tauri2.0-vue3-os
1
tauri2+vue3桌面os
1
tauri2-macos
1
tauri2-winos
1
tauri2.0仿macos
1
tauri2+vite桌面端os
1
flutter3直播app
1
flutter3仿抖音app
1
flutter3短视频直播
1
flutter3聊天室
1
flutter3仿携程
1
flutter3-trip
1
flutter3酒店预订
1
flutter3预约酒店app
1
flutter3旅行酒店app
1
vue3+deepseek
1
vue3-deepseek-chat
1
vue3仿deepseek流式ai
2
vue3智能ai聊天
1
vue3+deepseek-v3
1
vue3网页版ai
1
vue3-web-deepseek
1
vue3.5-webseek
1
社区赞助商