代码更新
This commit is contained in:
@@ -28,13 +28,11 @@ export const $types = [{
|
||||
|
||||
// 商品默认sku
|
||||
export const $defaultSku = {
|
||||
originPrice: '',
|
||||
costPrice: '',
|
||||
salePrice: '',
|
||||
memberPrice: '',
|
||||
costPrice: '',
|
||||
originPrice: '',
|
||||
// stockNumber: '',
|
||||
firstShared: '',
|
||||
suit: 1,
|
||||
suitNum: '',
|
||||
barCode: `${uni.getStorageSync("shopId")}${dayjs().valueOf()}`,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,17 @@ export default {
|
||||
label: '待支付'
|
||||
},
|
||||
{
|
||||
key: 'unsend',
|
||||
label: '待发货'
|
||||
key: 'in-production',
|
||||
label: '制作中'
|
||||
},
|
||||
{
|
||||
key: 'closed',
|
||||
key: 'wait-out',
|
||||
label: '待取餐'
|
||||
},
|
||||
{
|
||||
key: 'done',
|
||||
label: '订单完成'
|
||||
},
|
||||
{
|
||||
key: 'send',
|
||||
label: '已发'
|
||||
},
|
||||
{
|
||||
key: 'refunding',
|
||||
label: '申请退单'
|
||||
@@ -24,26 +24,30 @@ export default {
|
||||
key: 'refund',
|
||||
label: '退单'
|
||||
},
|
||||
{
|
||||
key: 'part-refund',
|
||||
label: '部分退单'
|
||||
},
|
||||
{
|
||||
key: 'cancelled',
|
||||
label: '取消订单'
|
||||
},
|
||||
{
|
||||
key: 'merge',
|
||||
label: '合台'
|
||||
},
|
||||
{
|
||||
key: 'pending',
|
||||
label: '挂单'
|
||||
},
|
||||
{
|
||||
key: 'activate',
|
||||
label: '激活'
|
||||
},
|
||||
{
|
||||
key: 'paying',
|
||||
label: '支付中'
|
||||
}
|
||||
// {
|
||||
// key: 'merge',
|
||||
// label: '合台'
|
||||
// },
|
||||
// {
|
||||
// key: 'pending',
|
||||
// label: '挂单'
|
||||
// },
|
||||
// {
|
||||
// key: 'activate',
|
||||
// label: '激活'
|
||||
// },
|
||||
// {
|
||||
// key: 'paying',
|
||||
// label: '支付中'
|
||||
// }
|
||||
],
|
||||
sendType: [
|
||||
{
|
||||
|
||||
@@ -1,36 +1,33 @@
|
||||
export const $status = {
|
||||
pending: {
|
||||
label: "挂单中",
|
||||
type: "#E6A23C",
|
||||
},
|
||||
using: {
|
||||
idle: {
|
||||
label: "空闲",
|
||||
type: "#3F9EFF",
|
||||
},
|
||||
using: {
|
||||
label: "使用中",
|
||||
type: "#fa5555",
|
||||
},
|
||||
subscribe: {
|
||||
label: "预定",
|
||||
type: "rgb(34, 191, 100)",
|
||||
},
|
||||
closed: {
|
||||
label: "关台",
|
||||
type: "rgb(221,221,221)",
|
||||
},
|
||||
opening: {
|
||||
label: "开台中",
|
||||
type: "#fa5555",
|
||||
},
|
||||
paying: {
|
||||
label: "结算中",
|
||||
type: "#E6A23C",
|
||||
},
|
||||
idle: {
|
||||
label: "空闲",
|
||||
type: "#3F9EFF",
|
||||
},
|
||||
subscribe: {
|
||||
label: "预定",
|
||||
type: "rgb(34, 191, 100)",
|
||||
},
|
||||
closed: {
|
||||
label: "关台",
|
||||
type: "rgb(221,221,221)",
|
||||
},
|
||||
// opening: {
|
||||
// label: "开台中",
|
||||
// type: "#67C23A",
|
||||
// },
|
||||
cleaning: {
|
||||
label: "待清台",
|
||||
type: "#FAAD14",
|
||||
},
|
||||
cleaning: {
|
||||
label: "待清台",
|
||||
type: "#FAAD14",
|
||||
},
|
||||
// paying: {
|
||||
// label: "结算中",
|
||||
// type: "#E6A23C",
|
||||
// },
|
||||
|
||||
unbind: {
|
||||
label: "未绑定",
|
||||
type: "rgb(221,221,221)",
|
||||
|
||||
@@ -17,7 +17,7 @@ export function canTuicai(orderInfo, item) {
|
||||
return orderInfo.status == 'unpaid' && orderInfo.useType != 'dine-in-before' && item.status != 'return'
|
||||
}
|
||||
export function canTuiKuan(orderInfo, item) {
|
||||
return orderInfo.status == 'closed' && item.status != 'return' && item.status != 'refund' && item.status !=
|
||||
return orderInfo.status == 'done' && item.status != 'return' && item.status != 'refund' && item.status !=
|
||||
'refunding'
|
||||
}
|
||||
export function isTuiCai(item) {
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
$hasPermission
|
||||
} from '@/http/yskApi/shop.js'
|
||||
import { $hasPermission } from '@/http/yskApi/shop.js'
|
||||
import infoBox from '@/commons/utils/infoBox.js'
|
||||
|
||||
const $PermissionObj = {
|
||||
@@ -147,17 +145,18 @@ export async function hasPermission(params) {
|
||||
if (!params) {
|
||||
return infoBox.showToast('未找到相关权限,请检查代码或在权限配置文件commons/utils/hasPermission.js文件进行修改或增加')
|
||||
}
|
||||
const option = Object.assign({
|
||||
tips: true,
|
||||
key: '',
|
||||
text: ''
|
||||
}, params)
|
||||
const res = await $hasPermission({
|
||||
code: params.key
|
||||
})
|
||||
if (!res && option.tips) {
|
||||
infoBox.showToast('您没有' + params.text + '权限!')
|
||||
}
|
||||
return res
|
||||
// const option = Object.assign({
|
||||
// tips: true,
|
||||
// key: '',
|
||||
// text: ''
|
||||
// }, params)
|
||||
// const res = await $hasPermission({
|
||||
// code: params.key
|
||||
// })
|
||||
// if (!res && option.tips) {
|
||||
// infoBox.showToast('您没有' + params.text + '权限!')
|
||||
// }
|
||||
// return res
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
import { $getBaiduToken } from '@/http/apiManager.js';
|
||||
const audioTeam = [];
|
||||
let audioStartSwitch = false;
|
||||
const getAudioUrl = 'https://tsn.baidu.com/text2audio';
|
||||
|
||||
export default function openVoice(objs) { // 传入需转为语音的文本内容
|
||||
let lineUp = false;
|
||||
let returnAudio = false;
|
||||
if (typeof(objs) !== 'string') {
|
||||
if (objs && objs.lineUp === true) {
|
||||
lineUp = true;
|
||||
}
|
||||
if (objs && objs.returnAudio === true) {
|
||||
returnAudio = true;
|
||||
}
|
||||
}
|
||||
if(returnAudio) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
openVoiceFc(objs, returnAudio).then(res=>{
|
||||
resolve(res);
|
||||
}).catch(err=>{
|
||||
reject(err)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
if (!audioStartSwitch || lineUp) {
|
||||
audioStartSwitch = true;
|
||||
openVoiceFc(objs);
|
||||
} else {
|
||||
audioTeam.push(objs);
|
||||
}
|
||||
}
|
||||
|
||||
function openVoiceFc(objs, returnAudio) {
|
||||
if(returnAudio) {
|
||||
return new Promise((resolve, reject)=>{
|
||||
$getBaiduToken().then(({bizData}) => {
|
||||
if (bizData) {
|
||||
resolve(tts(objs, bizData, returnAudio));
|
||||
} else {
|
||||
reject('获取语音tok接口为空');
|
||||
}
|
||||
})
|
||||
})
|
||||
}else{
|
||||
$getBaiduToken().then(({bizData}) => {
|
||||
if (bizData) {
|
||||
tts(objs, bizData);
|
||||
} else {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function tts(objs, tok, returnAudio) {
|
||||
if(typeof(objs)=='string')
|
||||
objs = {voiceSet: {tex: objs}};
|
||||
const data = {
|
||||
tok,
|
||||
cuid: tok,
|
||||
ctp: 1,
|
||||
lan: 'zh',
|
||||
...objs.voiceSet
|
||||
}
|
||||
if(returnAudio)
|
||||
return btts( data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
|
||||
btts( data, objs.audioSet, objs.audioCallback, objs.lineUp, returnAudio);
|
||||
}
|
||||
|
||||
function setAudioSet(options, audio) {
|
||||
if (options) {
|
||||
audio.volume = options.volume || 1;
|
||||
audio.startTime = options.startTime || 0;
|
||||
audio.loop = options.loop || false;
|
||||
audio.obeyMuteSwitch = options.obeyMuteSwitch && typeof(options.obeyMuteSwitch) == 'boolean' ? options.obeyMuteSwitch :
|
||||
true; //支持微信小程序、百度小程序、头条小程序
|
||||
}
|
||||
}
|
||||
|
||||
function btts(param, options, audioCallback, lineUp, returnAudio) {
|
||||
let audio = uni.createInnerAudioContext();
|
||||
setAudioSet(options, audio);
|
||||
// 序列化参数列表
|
||||
let fd = [];
|
||||
for (let k in param) {
|
||||
fd.push(k + '=' + encodeURIComponent(encodeURIComponent(param[k])));
|
||||
}
|
||||
audio.src = `${getAudioUrl}?${fd.join('&')}`;
|
||||
|
||||
if(returnAudio) {
|
||||
audio.onEnded(() => {
|
||||
audio.destroy(); //销毁音频实例
|
||||
audio = null;
|
||||
})
|
||||
audio.onError((e)=>{
|
||||
if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
|
||||
audio.destroy(); //销毁音频实例
|
||||
audio = null;
|
||||
})
|
||||
return audio;
|
||||
}
|
||||
audio.onPlay(() => {
|
||||
if (audioCallback && audioCallback.onPlay && typeof(audioCallback.onPlay) == 'function') audioCallback.onPlay();
|
||||
})
|
||||
audio.onPause(()=>{
|
||||
if (audioCallback && audioCallback.onPause && typeof(audioCallback.onPause) == 'function') audioCallback.onPause();
|
||||
})
|
||||
audio.onWaiting(()=>{
|
||||
if (audioCallback && audioCallback.onWaiting && typeof(audioCallback.onWaiting) == 'function') audioCallback.onWaiting();
|
||||
})
|
||||
audio.onStop(()=>{
|
||||
if (audioCallback && audioCallback.onStop && typeof(audioCallback.onStop) == 'function') audioCallback.onStop();
|
||||
})
|
||||
audio.onTimeUpdate(()=>{
|
||||
if (audioCallback && audioCallback.onTimeUpdate && typeof(audioCallback.onTimeUpdate) == 'function') audioCallback.onTimeUpdate();
|
||||
})
|
||||
audio.onSeeking(()=>{
|
||||
if (audioCallback && audioCallback.onSeeking && typeof(audioCallback.onSeeking) == 'function') audioCallback.onSeeking();
|
||||
})
|
||||
audio.onSeeked(()=>{
|
||||
if (audioCallback && audioCallback.onSeeked && typeof(audioCallback.onSeeked) == 'function') audioCallback.onSeeked();
|
||||
})
|
||||
audio.onEnded(() => {
|
||||
audio.destroy(); //销毁音频实例
|
||||
audio = null;
|
||||
if (audioCallback && audioCallback.onEnded && typeof(audioCallback.onEnded) == 'function') audioCallback.onEnded();
|
||||
if (lineUp !== false) {
|
||||
if (audioTeam.length > 0) {
|
||||
openVoiceFc(audioTeam[0]);
|
||||
audioTeam.splice(0, 1);
|
||||
} else {
|
||||
audioStartSwitch = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
audio.onError((e)=>{
|
||||
if (audioCallback && audioCallback.onError && typeof(audioCallback.onError) == 'function') audioCallback.onError(e);
|
||||
audio.destroy(); //销毁音频实例
|
||||
audio = null;
|
||||
})
|
||||
audio.play();
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
import dayjs from 'dayjs'
|
||||
import baiduyy from './QS-baiduyy.js'; // 百度语音合成
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
import wxTextToSpeach from './wxTextToSpeach.js'; // 微信小程序插件语音合成
|
||||
// #endif
|
||||
|
||||
|
||||
const model = {
|
||||
// 监听推送通知
|
||||
addPushMsgEventListener: function(){
|
||||
|
||||
console.log("监听推送")
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// unipush1.0监听消息
|
||||
if(plus && plus.push) {
|
||||
plus.push.addEventListener('receive', model.handlePush)
|
||||
}
|
||||
// #endif
|
||||
// unipush2.0监听消息
|
||||
model.uniPushListener2()
|
||||
},
|
||||
|
||||
|
||||
// uniPush2.0 接收推送消息
|
||||
uniPushListener2: function() {
|
||||
uni.onPushMessage((res) => {
|
||||
console.log("uniPush2.0 收到推送消息:", res.data) //监听推送消息
|
||||
model.handlePush(res.data)
|
||||
})
|
||||
},
|
||||
|
||||
// 语音播报
|
||||
handlePush: function(message) {
|
||||
|
||||
// 没有token信息
|
||||
if(!storageManage.token()){
|
||||
return false;
|
||||
}
|
||||
|
||||
// 信息不存在
|
||||
if(!message || !message.content) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const content = JSON.parse(message.content)
|
||||
console.log("消息内容:", content)
|
||||
|
||||
// 支付成功
|
||||
if (content && content.type == 'paySuccess') {
|
||||
// 在过期时间之内, 则调起语音播报。
|
||||
if( dayjs(content.expiredTime).isAfter(dayjs()) ){
|
||||
console.log('执行消息播报');
|
||||
// #ifdef MP-WEIXIN
|
||||
wxTextToSpeach(content.msg)
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
baiduyy(content.msg)
|
||||
// #endif
|
||||
uni.vibrateLong({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default model
|
||||
@@ -1,50 +0,0 @@
|
||||
import {
|
||||
$pushInfoRegister
|
||||
} from '@/http/apiManager.js'
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
// 默认导出 方法 注册 push连接
|
||||
export default async function() {
|
||||
let cid1 = undefined // unipush1.0 客户端CID
|
||||
let cid2 = undefined // unipush2.0 客户端CID
|
||||
let orgCid = undefined // 原始cid如果获取的cid和新的cid不相同赋值原始cid后端会根据原始cid更新
|
||||
let cidType = undefined //传递类型 是 app 还是 微信
|
||||
// #ifdef APP-PLUS
|
||||
cidType = 'app_plus'
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
cidType = 'mp_weixin'
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
if (!plus) {
|
||||
cid1 = plus.push.getClientInfo().clientid
|
||||
}
|
||||
// #endif
|
||||
const data = await uni.getPushClientId()
|
||||
console.log('客户端推送标识:', data.cid)
|
||||
cid2 = data.cid
|
||||
// 如果不存 cid 本地存储 写入 cid
|
||||
if (!storageManage.uniPush2Cid()) {
|
||||
storageManage.uniPush2Cid(data.cid)
|
||||
} else if (cid2 !== storageManage.uniPush2Cid()) { // 否则进行 cid 对比 判断 是否相等 不相等 赋值 orgCid
|
||||
orgCid = storageManage.uniPush2Cid() //赋值原始cid
|
||||
storageManage.uniPush2Cid(data.cid) //重新写入 cid
|
||||
}
|
||||
if (cid1) {
|
||||
pushInfoRegister(cid1)
|
||||
} else {
|
||||
pushInfoRegister(cid1, cid2, orgCid, cidType)
|
||||
}
|
||||
|
||||
function pushInfoRegister(cid1 = '', cid2 = '', org = '', cidType = '') {
|
||||
$pushInfoRegister({
|
||||
cid1,
|
||||
cid2,
|
||||
orgCid: org,
|
||||
cidType
|
||||
}).then(res => {
|
||||
orgCid = '' //重置 数据
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { $mchConfig } from "@/http/apiManager"
|
||||
import storageManage from '@/commons/utils/storageManage.js'
|
||||
let num = 0 //计算错误此时 超过5次错误 不在出触发
|
||||
const plugin = requirePlugin("WechatSI")
|
||||
const pushMsgArr = [] //维护一个消息队列
|
||||
let backgroundAudioManager = undefined //获取背景音频实例
|
||||
let audioMp3 = ''
|
||||
console.log('执行创建 语音播报逻辑');
|
||||
// 获取配置项 判断是否 开启 小程序 语音推送
|
||||
export function getPushStatus () {
|
||||
if (!storageManage.token()) return //未登录 不播放
|
||||
$mchConfig('orderConfig').then(({ bizData = [] }) => {
|
||||
const weChat = bizData.find(v => v.configKey == "weChatVoice")
|
||||
if (weChat && weChat?.configVal == 1) {
|
||||
createBgMusice()
|
||||
}
|
||||
})
|
||||
}
|
||||
// getPushStatus()
|
||||
// 创建 背景音乐
|
||||
function createBgMusice (file) {
|
||||
backgroundAudioManager = wx.getBackgroundAudioManager()
|
||||
backgroundAudioManager.title = '订单通知'
|
||||
if (!audioMp3) {
|
||||
createFile()
|
||||
} else {
|
||||
backgroundAudioManager.src = audioMp3
|
||||
}
|
||||
|
||||
// 监听 音频播放失败事件
|
||||
backgroundAudioManager.onError(function (res) {
|
||||
console.log('音频播放失败', res, num);
|
||||
if (num >= 5) return
|
||||
createFile()
|
||||
num++
|
||||
})
|
||||
// 监听 音频播放结束事件
|
||||
onBgMusiceEnd()
|
||||
}
|
||||
// 监听bei背景音乐播放状态
|
||||
export function onBgMusiceEnd () {
|
||||
backgroundAudioManager.onEnded(() => {
|
||||
if (pushMsgArr.length > 0) return broadcast(pushMsgArr.pop()) //如果有消息 则继续播放
|
||||
backgroundAudioManager.src = audioMp3 //否则播放默认背景音乐
|
||||
})
|
||||
}
|
||||
export function startOrEndMusice (flag) {
|
||||
if (!flag && !!backgroundAudioManager) return backgroundAudioManager.stop() //关闭背景音乐 地址指向空即可
|
||||
if (!backgroundAudioManager) return createBgMusice() // 如果一开始是关闭状态 则创建背景音乐实例
|
||||
backgroundAudioManager.src = audioMp3 // 否则重新赋值背景音地址即可
|
||||
}
|
||||
export default function (message) {
|
||||
if (!backgroundAudioManager) return
|
||||
pushMsgArr.unshift(message) //将消息添加到消息队列头部 背景音乐播放结束后 会对消息队列 进行校验 如果消息队列有消息 会进行播放 否则继续循环背景音乐
|
||||
}
|
||||
// 播放订单
|
||||
function broadcast (msg) {
|
||||
plugin.textToSpeech({
|
||||
lang: "zh_CN",
|
||||
tts: true,
|
||||
content: msg,
|
||||
success: function (res) {
|
||||
backgroundAudioManager.src = res.filename;
|
||||
onBgMusiceEnd()
|
||||
},
|
||||
fail: function (res) {
|
||||
console.log("fail tts", res)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 创建文件
|
||||
export function createFile (file) {
|
||||
const fs = wx.getFileSystemManager()
|
||||
fs.copyFile({
|
||||
srcPath: `static/noiseless.mp3`,
|
||||
destPath: `${wx.env.USER_DATA_PATH}/noiseless.mp3`,
|
||||
success (res) {
|
||||
console.log(res, `${wx.env.USER_DATA_PATH}/noiseless.mp3`)
|
||||
audioMp3 = `${wx.env.USER_DATA_PATH}/noiseless.mp3`
|
||||
backgroundAudioManager.src = audioMp3
|
||||
},
|
||||
fail (res) {
|
||||
console.error(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
创建 云空间 上传云函数 云函数 url化 运营平台 配置云函数地址
|
||||
|
||||
打包时 勾选云push 2.0 push1.0 仅支持 app 推送
|
||||
|
||||
注意配置 百度语音相关参数
|
||||
|
||||
使用push2.0 请将 static\noiseless.mp3 文件 配置到运营平台 系统 配置 通知配置 push2.0 uniPush语音播报音频文件(小程序播报必填) 下
|
||||
|
||||
注意:扩展库依赖3张opendb表:opendb-tempdata,opendb-device,uni-id-device。公测版uniCloud,执行扩展库会自动创建。如果你使用的是uniCloud正式版需要自己创建这3张表。
|
||||
|
||||
@@ -18,15 +18,10 @@ const appCache = {
|
||||
const model = {
|
||||
|
||||
setLogin(res){
|
||||
const user=res.user.user
|
||||
uni.setStorageSync('logoutHandle',false)
|
||||
uni.setStorageSync('shopId', res.shopId)
|
||||
uni.setStorageSync('shopName',res.shopName)
|
||||
uni.setStorageSync('logo',res.logo)
|
||||
uni.setStorageSync('shopInfo',res.shopInfo)
|
||||
uni.setStorageSync('loginType',res.loginType)
|
||||
uni.setStorageSync('shopUserId',user.id)
|
||||
if(res.loginType=='staff'){
|
||||
uni.setStorageSync('merchantName',user.createBy||user.updateBy)
|
||||
if(res.loginType=='1'){
|
||||
// uni.setStorageSync('merchantName',user.createBy||user.updateBy)
|
||||
}
|
||||
},
|
||||
// 退出清空所有的缓存数据。 (不包含 环境相关)
|
||||
@@ -51,14 +46,14 @@ const model = {
|
||||
|
||||
if (val) {
|
||||
// 有值,为放置
|
||||
appCache.tokenVal = val
|
||||
appCache.tokenVal = val.tokenValue
|
||||
uni.setStorageSync(appConfig.tokenKey, val)
|
||||
} else {
|
||||
// 否则为获取
|
||||
|
||||
if (!appCache.tokenVal) {
|
||||
//缓存取不到,获取应用本地信息
|
||||
appCache.tokenVal = uni.getStorageSync(appConfig.tokenKey)
|
||||
appCache.tokenVal = uni.getStorageSync(appConfig.tokenKey).tokenValue
|
||||
}
|
||||
return appCache.tokenVal
|
||||
}
|
||||
@@ -254,6 +249,8 @@ const model = {
|
||||
if (envMode) {
|
||||
uni.setStorageSync(appConfig.storeEnvEnumKey, envMode) // 改变存储
|
||||
}
|
||||
console.log(appConfig.storeEnvEnumKey)
|
||||
|
||||
return uni.getStorageSync(appConfig.storeEnvEnumKey)
|
||||
},
|
||||
|
||||
|
||||
140
commons/utils/websocket.js
Normal file
140
commons/utils/websocket.js
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
import { reactive, ref } from 'vue';
|
||||
// WebSocket 工具类,封装了 WebSocket 的连接、发送、接收、心跳、重连和关闭等操作
|
||||
class WebsocketUtil {
|
||||
|
||||
// 构造函数,初始化 WebSocket 连接
|
||||
constructor(url, time, params) {
|
||||
this.url = url; // WebSocket 服务器的 URL
|
||||
this.params = params; // WebSocket 服务器的 URL
|
||||
this.time = time; // 心跳发送的间隔时间(秒)
|
||||
this.socketTask = null; // WebSocket 任务对象
|
||||
this.isOpen = false; // WebSocket 连接是否打开
|
||||
this.reconnectTimeout = null; // 重连定时器
|
||||
this.heartbeatInterval = null; // 心跳定时器
|
||||
this.messageCallbacks = []; // 存储外部注册的消息回调函数的数组
|
||||
|
||||
// 初始化 WebSocket 连接
|
||||
this.initializeWebSocket();
|
||||
}
|
||||
|
||||
// 初始化 WebSocket 连接
|
||||
initializeWebSocket() {
|
||||
this.socketTask = uni.connectSocket({
|
||||
url: this.url,
|
||||
success: () => {
|
||||
console.log('WebSocket连接成功');
|
||||
|
||||
return this.socketTask;
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('WebSocket连接失败', error);
|
||||
this.reconnect();
|
||||
}
|
||||
});
|
||||
|
||||
this.socketTask.onOpen((res) => {
|
||||
console.log('WebSocket连接正常!==',res);
|
||||
this.isOpen = true;
|
||||
// 连接成功后启动心跳和消息监听
|
||||
this.startHeartbeat();
|
||||
this.listenForMessages();
|
||||
// 注意:这里的 onClose 监听器应该放在 uni.connectSocket 调用之后
|
||||
this.socketTask.onClose((result) => {
|
||||
this.isOpen = false;
|
||||
// if( this.isOpen ){
|
||||
this.reconnect();
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 启动心跳检测
|
||||
startHeartbeat() {
|
||||
if (this.heartbeatInterval) {
|
||||
clearInterval(this.heartbeatInterval);
|
||||
}
|
||||
this.heartbeatInterval = setInterval(() => {
|
||||
if (this.isOpen) {
|
||||
this.send('心跳检测','heartbeat');
|
||||
}
|
||||
}, this.time);
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
send(data,type) {
|
||||
if (this.socketTask && this.isOpen) {
|
||||
this.socketTask.send({
|
||||
data: data,
|
||||
type: type||'heartbeat',
|
||||
success: (res) => {
|
||||
// console.log('消息发送成功', res);
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('消息发送失败', error);
|
||||
this.reconnect(); // 这里可能需要根据实际情况判断是否重连
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 监听 WebSocket 消息
|
||||
listenForMessages() {
|
||||
if (this.socketTask) {
|
||||
this.socketTask.onMessage((res) => {
|
||||
const { data } = res;
|
||||
this.messageCallbacks.forEach(callback => callback(data.toString())); // 假设 data 是字符串或可转换为字符串
|
||||
});
|
||||
} else {
|
||||
console.error('WebSocket 连接尚未建立,无法监听消息');
|
||||
}
|
||||
}
|
||||
|
||||
// 重连 WebSocket
|
||||
reconnect() {
|
||||
if (this.reconnectTimeout) {
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
}
|
||||
this.reconnectTimeout = setTimeout(() => {
|
||||
this.initializeWebSocket();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// 关闭 WebSocket 连接
|
||||
closeSocket() {
|
||||
if (this.socketTask) {
|
||||
uni.closeSocket({
|
||||
success: () => {
|
||||
console.log('WebSocket连接已关闭');
|
||||
this.isOpen = false;
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('关闭WebSocket连接失败', error);
|
||||
}
|
||||
});
|
||||
this.socketTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 外部注册消息回调函数
|
||||
onMessage(callback) {
|
||||
this.messageCallbacks.push(callback);
|
||||
}
|
||||
|
||||
// 外部注销消息回调函数
|
||||
offMessage(callback) {
|
||||
this.messageCallbacks = this.messageCallbacks.filter(cb => cb !== callback);
|
||||
}
|
||||
|
||||
// 销毁 WebSocket 连接,清理资源
|
||||
destroy() {
|
||||
this.closeSocket();
|
||||
clearInterval(this.heartbeatInterval);
|
||||
clearTimeout(this.reconnectTimeout);
|
||||
this.messageCallbacks = [];
|
||||
}
|
||||
}
|
||||
|
||||
export default WebsocketUtil;
|
||||
Reference in New Issue
Block a user