<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      uniapp+vue3聊天室|uni-app+vite4+uv-ui跨端仿微信app聊天語音/朋友圈

      原創研發uniapp+vue3+pinia2三端仿微信app聊天模板Uniapp-Wechat

      uni-vue3-wchat基于uni-app+vue3+pinia2+uni-ui+uv-ui等技術跨端仿制微信App界面聊天項目,支持編譯到H5+小程序端+App端。實現編輯框多行消息/emoj混合、長按觸摸式仿微信語音面板、圖片/視頻預覽、紅包/朋友圈等功能。

      預覽圖

      編譯至h5+App端+小程序端運行效果

      技術棧

      • 開發工具:HbuilderX 4.0.8
      • 技術框架:Uniapp+Vue3+Pinia2+Vite4.x
      • UI組件庫:uni-ui+uv-ui(uniapp+vue3組件庫)
      • 彈框組件:uv3-popup(自定義uniapp+vue3多端彈框組件)
      • 自定義組件:uv3-navbar導航欄+uv3-tabbar菜單欄
      • 緩存技術:pinia-plugin-unistorage
      • 支持編譯:H5+小程序+APP端

      目前uni-app對vue3支持性已經蠻不錯了。之前也有給大家分享一款uniapp+vue3短視頻/直播商城項目。

      http://www.rzrgm.cn/xiaoyan2017/p/17938517

      uniapp-vue3-wchat基于最新跨端技術開發,支持編譯H5/小程序端/APP端,運行效果基本保持一致。

      項目構建目錄

      支持在pc端以750px像素布局顯示。

      目前uni-wechat項目同步上線到我的作品集,如果恰好有需要,歡迎自行去拍哈~ 感謝小伙伴們的支持!

      原創uni-app+vue3+uv-ui跨端仿微信app聊天室

      整個項目采用vue3 setup語法糖編碼開發。

      App.vue配置

      項目主模板App.vue使用vue3 setup語法。

      <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>

      uni-app+vue3自定義導航條+菜單欄

      components目錄下自定義導航欄Navbar和底部菜單欄Tabbar組件。

      navbar導航條支持是否顯示返回、自定義標題(居中)、背景色/文字顏色、搜索等功能。

      支持如下自定義插槽

      <slot #back />
      <slot #backText />
      <slot #left />
      <slot #title />
      <slot #search />
      <slot #right />
      <uv3-navbar :back="true" title="標題內容" bgcolor="#07c160" color="#fff" fixed zIndex="1010" />
      
      <uv3-navbar custom bgcolor="linear-gradient(to right, #07c160, #0000ff)" color="#fff" center transparent zIndex="2024">
          <template #back><uni-icons type="close" /></template>
          <template #backText><text>首頁</text></template>
          <template #title>
              <image src="/static/logo.jpg" style="height:20px;width:20px;" /> Admin
          </template>
          <template #right>
              <view class="ml-20" @click="handleAdd"><text class="iconfont icon-tianjia"></text></view>
              <view class="ml-20"><text class="iconfont icon-msg"></text></view>
          </template>
      </uv3-navbar>

      uni-vue3-wchat布局模板

      由于整體項目結構采用頂部導航區域+主體內容區+底部區域,所以新建一個公共布局模板。

        

      <!-- 公共布局模板 -->
      
      <!-- #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實現微信九宮格圖像

      <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>

      uniapp+vue3自定義彈出框

      項目中所有的彈窗效果都是基于uniapp+vue3自定義組件實現功能。

        

        

        

      支持如下參數配置:

      v-model        當前組件是否顯示
      title          標題(支持富文本div標簽、自定義插槽內容)
      content        內容(支持富文本div標簽、自定義插槽內容)
      type           彈窗類型(toast | footer | actionsheet | actionsheetPicker | android/ios)
      customStyle    自定義彈窗樣式
      icon           toast圖標(loading | success | fail | warn | info)
      shade          是否顯示遮罩層
      shadeClose     是否點擊遮罩時關閉彈窗
      opacity        遮罩層透明度
      round          是否顯示圓角
      xclose         是否顯示關閉圖標
      xposition      關閉圖標位置(left | right | top | bottom)
      xcolor         關閉圖標顏色
      anim           彈窗動畫(scaleIn | fadeIn | footer | fadeInUp | fadeInDown)
      position       彈出位置(top | right | bottom | left)
      follow         長按/右鍵彈窗(坐標點)
      time           彈窗自動關閉秒數(1、2、3)
      zIndex         彈窗層疊(默認202107)
      btns           彈窗按鈕(參數:text|style|disabled|click)
      ------------------------------------------
      ## slot [插槽]
      <template #title></template>
      <template #content></template>
      ------------------------------------------
      ## emit
      open        打開彈出層時觸發(@open="xxx")
      close       關閉彈出層時觸發(@close="xxx")

      支持組件式+函數式調用。

      <script setup>
          import { onMounted, ref, computed, watch, nextTick, getCurrentInstance } from 'vue'
          
          const props = defineProps({
              ...
          })
          const emit = defineEmits([
              'update:modelValue',
              'open',
              'close'
          ])
          
          const instance = getCurrentInstance()
          
          const opts = ref({
              ...props
          })
          const visible = ref(false)
          const closeAnim = ref(false)
          const stopTimer = ref(null)
          const oIndex = ref(props.zIndex)
          const uuid = computed(() => Math.floor(Math.random() * 10000))
          
          const positionStyle = ref({ position: 'absolute', left: '-999px', top: '-999px' })
          
          const toastIcon = {
              ...
          }
          
          // 打開彈框
          const open = (options) => {
              if(visible.value) return
              opts.value = Object.assign({}, props, options)
              // console.log('-=-=混入參數:', opts.value)
              visible.value = true
              
              // nvue 的各組件在安卓端默認是透明的,如果不設置background-color,可能會導致出現重影的問題
              // #ifdef APP-NVUE
              if(opts.value.customStyle && !opts.value.customStyle['background'] && !opts.value.customStyle['background-color']) {
                  opts.value.customStyle['background'] = '#fff'
              }
              // #endif
              
              let _index = ++index
              oIndex.value = _index + parseInt(opts.value.zIndex)
              
              emit('open')
              typeof opts.value.onOpen === 'function' && opts.value.onOpen()
              
              // 長按處理
              if(opts.value.follow) {
                  nextTick(() => {
                      let winW = uni.getSystemInfoSync().windowWidth
                      let winH = uni.getSystemInfoSync().windowHeight
                      // console.log('坐標點信息:', opts.value.follow)
                      getDom(uuid.value).then(res => {
                          // console.log('Dom尺寸信息:', res)
                          if(!res) return
                          
                          let pos = getPos(opts.value.follow[0], opts.value.follow[1], res.width+15, res.height+15, winW, winH)
                          positionStyle.value.left = pos[0] + 'px'
                          positionStyle.value.top = pos[1] + 'px'
                      })
                  })
              }
              
              if(opts.value.time) {
                  if(stopTimer.value) clearTimeout(stopTimer.value)
                  stopTimer.value = setTimeout(() => {
                      close()
                  }, parseInt(opts.value.time) * 1000)
              }
          }
          
          // 關閉彈框
          const close = () => {
              if(!visible.value) return
              
              closeAnim.value = true
              setTimeout(() => {
                  visible.value = false
                  closeAnim.value = false
                  
                  emit('update:modelValue', false)
                  emit('close')
                  typeof opts.value.onClose === 'function' && opts.value.onClose()
                  
                  positionStyle.value.left = '-999px'
                  positionStyle.value.top = '-999px'
                  
                  stopTimer.value && clearTimeout(stopTimer.value)
              }, 200)
          }
          
          // 點擊遮罩層
          const handleShadeClick = () => {
              if(JSON.parse(opts.value.shadeClose)) {
                  close()
              }
          }
          
          // 按鈕事件
          const handleBtnClick = (e, index) => {
              let btn = opts.value.btns[index]
              if(!btn?.disabled) {
                  console.log('按鈕事件類型:', typeof btn.click)
                  
                  typeof btn.click === 'function' && btn.click(e)
              }
          }
          
          // 獲取dom寬高
          const getDom = (id) => {
              return new Promise((resolve, inject) => {
                  // uniapp vue3中 uni.createSelectorQuery().in(this) 會報錯__route__未定義  https://ask.dcloud.net.cn/question/140192
                  uni.createSelectorQuery().in(instance).select('#uapopup-' + id).fields({
                      size: true,
                  }, data => {
                      resolve(data)
                  }).exec()
              })
          }
          
          // 自適應坐標點
          const getPos = (x, y, ow, oh, winW, winH) => {
              let l = (x + ow) > winW ? x - ow : x
              let t = (y + oh) > winH ? y - oh : y
              return [l, t]
          }
          
          onMounted(() => {
              if(props.modelValue) {
                  open()
              }
          })
      
          watch(() => props.modelValue, (val) => {
              // console.log(val)
              if(val) {
                  open()
              }else {
                  close()
              }
          })
          
          defineExpose({
              open,
              close
          })
      </script>

      uniapp+vue3聊天模塊

        

      uniapp+vue3實現增強版文本輸入框。支持獲取焦點高亮邊框、單行(input)+多行(textarea)輸入模式,自定義前綴/后綴圖標。

      該插件已經免費發布到插件應用市場,有需要的可以去看看哈~

      如上圖:實現了類似微信按住說話功能。

      <!-- 語音操作面板 -->
      <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>

      OK,以上就是uni-app+vue3開發多端聊天app實例的一些知識分享,希望對大家有所幫助!

      flutter3-deepseek流式AI模板|Flutter3.27+Dio+DeepSeeek聊天ai助手

      Uniapp-DeepSeek跨三端AI助手|uniapp+vue3+deepseek-v3流式ai聊天模板

      Electron35-DeepSeek桌面端AI系統|vue3.5+electron+arco客戶端ai模板

      Vite5+Electron聊天室|electron31跨平臺仿微信EXE客戶端|vue3聊天程序

      Electron31-Vue3Admin管理系統|vite5+electron+pinia桌面端后臺Exe

      Tauri2.0-Vue3OS桌面端os平臺|tauri2+vite6+arco電腦版OS管理系統

      最后附上幾個最新實戰項目

      uniapp+vite酒店預訂app模板:http://www.rzrgm.cn/xiaoyan2017/p/18592873

      uniapp+vue3手機版os系統:http://www.rzrgm.cn/xiaoyan2017/p/18204751

      flutter3.27短視頻直播商城:http://www.rzrgm.cn/xiaoyan2017/p/18700875

      flutter3+window_manager仿macOS桌面系統:http://www.rzrgm.cn/xiaoyan2017/p/18132176

      flutter3.27仿攜程app酒店預訂系統:http://www.rzrgm.cn/xiaoyan2017/p/18726313

       

      posted @ 2024-04-29 13:56  xiaoyan2017  閱讀(2776)  評論(1)    收藏  舉報
      友情鏈接: UP主小店B站
      主站蜘蛛池模板: 久在线视频播放免费视频| 色香欲天天影视综合网| 久久精品国产一区二区三| 男人扒女人添高潮视频| 99久久亚洲精品无码毛片 | 精品无码久久久久久尤物| 婷婷综合缴情亚洲| 日本在线 | 中文| 亚洲狠狠爱一区二区三区| 亚洲夜色噜噜av在线观看| 国产嫩草精品网亚洲av| 天天澡日日澡狠狠欧美老妇| 欧洲精品码一区二区三区| 57pao成人国产永久免费视频| 国产网友愉拍精品视频手机| 曲周县| 国产又色又爽又高潮免费| 一区二区三区不卡国产| 高青县| 色欧美片视频在线观看| 成人性影院| 国产欧美精品一区aⅴ影院| 人妻中文字幕精品一页| 国产乱子伦一区二区三区四区五区 | 日韩免费无码视频一区二区三区 | 成人精品日韩专区在线观看| 成人免费乱码大片a毛片| 青草青草视频2免费观看| 亚洲另类激情专区小说图片| 无码人妻一区二区三区兔费| 噜噜综合亚洲av中文无码| 丰满人妻熟妇乱又精品视| 97精品人妻系列无码人妻| 国产嫩草精品网亚洲av| 精品亚洲精品日韩精品| 宿迁市| 一日本道伊人久久综合影 | 粗了大了 整进去好爽视频| 污污网站18禁在线永久免费观看| 精品一区二区免费不卡| 高清有码国产一区二区|