uniapp实现顶部弹窗通知,支持H5、App端
文件结构:
h5_push.vue
<template> <view> <transition name="slide-fade"> <view class="h5_push" v-if="show" @tap="handleClick" :style="style"> <view class="push-title"> <view class="push-type"> <image src="/static/message-icon.png"></image> {{ messageType }} </view> {{ messageTime }} </view> <view class="push-body"> <view class="push-content"> <view class="push-content-title">{{ messageTitle }}</view> <view class="push-content-text">{{ messageContent }}</view> </view> <image :src="messageImage" class="push-img" mode="aspectFill"></image> </view> </view> </transition> </view> </template> <script> export default { data() { return { show: false, // 关闭时间 closeTime: 3000, // app内横幅提醒 inApp: false, // 声音提醒 voice: true, // 振动提醒 vibration: false, // 消息分类 messageType: '', // 通知标题 messageTitle: '', // 时间 messageTime: '现在', // 通知文案 messageContent: '', // 缩略图 messageImage: '', tap: () => {}, top: 20, left: 20, } }, computed: { style() { let system = uni.getSystemInfoSync() let statusBarHeight = system.statusBarHeight return `top: calc(${statusBarHeight}px + ${this.top}rpx);left: ${this.left}rpx` }, }, created() { setTimeout(() => { this.show = false }, this.closeTime) }, methods: { handleClick() { this.tap() this.show = false } }, } </script> <style lang="scss" scoped> .h5_push { width: 710rpx; height: 192rpx; background: #ffffff; box-shadow: 0 3rpx 18rpx 0 rgba(54, 58, 68, 0.08); border-radius: 20rpx; position: fixed; z-index: 9999999; .push-title { padding: 30rpx 30rpx 15rpx; display: flex; align-items: center; justify-content: space-between; font-size: 24rpx; font-weight: 400; color: #4f555b; .push-type { display: flex; align-items: center; font-size: 24rpx; font-weight: 400; color: #4f555b; image { width: 24rpx; height: 24rpx; margin-right: 10rpx; } } } .push-body { display: flex; align-items: center; justify-content: space-between; padding: 0 24rpx 0 30rpx; .push-content { width: calc(100% - 150rpx); .push-content-title { font-size: 30rpx; font-weight: 500; color: #202123; margin-bottom: 20rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .push-content-text { font-size: 24rpx; font-weight: 400; color: #4f555b; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } .push-img { width: 100rpx; height: 100rpx; background: #f2f2f3; border: 1rpx solid #e9e9e9; border-radius: 10rpx; margin-left: 50rpx; } } } .slide-fade-enter-active { transition: all 0.3s ease; } .slide-fade-leave-active { transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1); } .slide-fade-enter, .slide-fade-leave-to /* .slide-fade-leave-active for below version 2.1.8 */ { transform: translateX(20rpx); opacity: 0; } </style>
app_push.js
export class appPush { constructor(option = {}) { console.log(option) // app内横幅提醒 this.inApp = option.inApp // 声音提醒 this.voice = option.voice // 振动提醒 this.vibration = option.vibration // 消息分类 this.messageType = option.messageType || '' // 通知标题 this.messageTitle = option.messageTitle || '' // 时间 this.messageTime = option.messageTime || '现在' // 通知文案 this.messageContent = option.messageContent || '' // 缩略图 this.messageImage = option.messageImage || '' this.tap = option.tap || (() => {}) this.screenWidth = plus.screen.resolutionWidth this.screenHeight = plus.screen.resolutionHeight // 比例 this.propotation = this.screenWidth / 750 //弹窗容器宽度 this.popupViewWidth = this.propotation * 710 // 弹窗容器高度 this.popupViewHeight = this.propotation * 192 // 弹窗容器的Padding this.viewContentPadding = this.propotation * 30 // 弹框容器的宽度 this.viewContentWidth = parseInt(this.popupViewWidth - this.viewContentPadding * 2) // 弹框到顶部的距离 this.system = uni.getSystemInfoSync() // 过度时间 this.duration = 200 // 关闭时间 this.closeTime = 3000 console.log(this.inApp, this.voice, this.vibration) this.top = this.propotation * 20 + this.system.statusBarHeight this.initTop = -this.system.statusBarHeight this.body = null this.bodyBg = null this.timer = null this.flag = false } // 生成弹框主体 createView() { let view = new plus.nativeObj.View('popupView', { // tag: 'rect', top: this.propotation * 20 + this.system.statusBarHeight, left: this.propotation * 20, height: this.popupViewHeight, width: this.popupViewWidth, }) // 绘制白色背景 view.drawRect({ color: '#fff', radius: '10px', }) let viewContentList = [ { src: '/static/message-icon.png', id: 'icon', tag: 'img', position: { top: this.viewContentPadding + 'px', left: this.viewContentPadding + 'px', width: this.propotation * 24 + 'px', height: this.propotation * 24 + 'px', }, }, { tag: 'font', id: 'pop-title', text: this.messageType, textStyles: { size: this.propotation * 24 + 'px', align: 'left', color: '#4F555B', }, position: { top: this.viewContentPadding + 'px', left: this.propotation * 64 + 'px', height: this.propotation * 24 + 'px', width: this.viewContentWidth + 'px', }, }, { tag: 'font', id: 'time', text: this.messageTime, textStyles: { size: this.propotation * 24 + 'px', align: 'right', color: '#4F555B', }, position: { top: this.viewContentPadding + 'px', left: this.viewContentPadding + 'px', height: this.propotation * 24 + 'px', width: this.viewContentWidth + 'px', }, }, { tag: 'font', id: 'push-title', text: this.messageTitle, textStyles: { size: this.propotation * 30 + 'px', align: 'left', color: '#202123', overflow: 'ellipsis', }, position: { top: this.propotation * 82 + 'px', left: this.propotation * 30 + 'px', height: this.propotation * 30 + 'px', width: this.propotation * 505 + 'px', }, }, { tag: 'font', id: 'push-content', text: this.messageContent, textStyles: { size: this.propotation * 24 + 'px', align: 'left', color: '#4F555B', overflow: 'ellipsis', }, position: { top: this.propotation * 130 + 'px', left: this.propotation * 30 + 'px', height: this.propotation * 24 + 'px', width: this.propotation * 505 + 'px', }, }, { src: this.messageImage, id: 'image', tag: 'img', position: { top: this.propotation * 68 + 'px', // right: "0px", left: this.propotation * 586 + 'px', width: this.propotation * 100 + 'px', height: this.propotation * 100 + 'px', }, }, ] view.draw(viewContentList) view.addEventListener('click', () => { this.tap() this.hide() }) this.body = view } // 显示/关闭弹框动画 modelAnimationOpenOrClose(type) { var options = { type: type, duration: this.duration } plus.nativeObj.View.startAnimation(options, this.body, () => { // 关闭原生动画 plus.nativeObj.View.clearAnimation() }) } bgAnimationOpenOrClose(type) { var options = { type: type, duration: this.duration } plus.nativeObj.View.startAnimation(options, this.bodyBg, () => { // 关闭原生动画 plus.nativeObj.View.clearAnimation() }) } // 显示弹框 show() { this.tips() if (this.inApp) { this.createView() this.body.show() setTimeout(() => { if (this.body) { this.hide() } }, this.closeTime) } } // 关闭弹框 hide() { this.modelAnimationOpenOrClose('slide-out-right') this.body.hide() setTimeout(() => { plus.nativeObj.View.clearAnimation() this.body = null }, this.duration) } // 调用系统提示音和振动 tips() { if (this.voice) { let main = plus.android.runtimeMainActivity() let RingtoneManager = plus.android.importClass('android.media.RingtoneManager') let uri = RingtoneManager.getActualDefaultRingtoneUri(main, RingtoneManager.TYPE_NOTIFICATION) console.log(uri) let MediaPlayer = plus.android.importClass('android.media.MediaPlayer') let player = MediaPlayer.create(main, uri) player.setLooping(false) player.prepare() player.start() } if (this.vibration) { plus.device.vibrate() } } } export default appPush
index.js
import app_push from './app_push.js' import h5Push from './h5_push.vue' const appPush = { install: function(Vue) { Vue.prototype.$appPush = function(op = {}) { // #ifdef APP-PLUS new app_push({ ...op }).show(); // #endif // #ifdef H5 // 创建构造器 const H5PushInstance = Vue.extend(h5Push) let instance = new H5PushInstance({ data: op }) instance.$mount() document.body.appendChild(instance.$el) Vue.nextTick(() => { instance.show = true }) // #endif } } } export default appPush
main.js
import appPush from '@/plugins/APPPush/index.js'
Vue.use(appPush)
使用:
let params = { inApp: true, // app内横幅提醒 voice: true, // 声音提醒 vibration: true, // 振动提醒 messageType: typeMap[res.type], messageTitle: res.name, messageContent: res.content, messageImage: "/static/58x58.png", tap: () => this.jump(res), }; this.$appPush(params);