文件结构:

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