From c89263a8cd6aa72e68becbb1466bc754693726bb Mon Sep 17 00:00:00 2001
From: D <3066417822@qq.com>
Date: Wed, 13 Sep 2023 01:32:10 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0websocket=E6=8F=92=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 79 ++++++++++++++++++++++---
src/App.vue | 13 +++++
src/plugins/index.ts | 3 +
src/plugins/socket.ts | 131 ++++++++++++++++++++++++++++++++++++++++++
src/utils/geek.ts | 20 ++++++-
5 files changed, 237 insertions(+), 9 deletions(-)
create mode 100644 src/plugins/socket.ts
diff --git a/README.md b/README.md
index b0482de..89d5af0 100644
--- a/README.md
+++ b/README.md
@@ -51,16 +51,79 @@ npm run dev:mp-weixin
4. 常用的订单组件
5. 信息展示组件
+# 插件的使用
+
+#### tab - 页面插件
+
+可以通过设置参数中的config.data来实现页面传参
+
+| 方法 | 作用 | 参数 |
+| ------------ | ------------------------------------------------ | ----------- |
+| getData | 可以拿到上个页面通过tab传递的参数 | 无 |
+| reLaunch | 关闭所有页面,打开到应用内的某个页面 | url、config |
+| switchTab | 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 | url、config |
+| redirectTo | 关闭当前页面,跳转到应用内的某个页面 | url、config |
+| navigateTo | 保留当前页面,跳转到应用内的某个页面 | url、config |
+| navigateBack | 关闭当前页面,返回上一页面或多级页面 | config |
+
+#### auth - 鉴权插件
+
+下面所有方法返回值都是布尔值,permission代表权限字符串,role代表角色字符串,复数形式代表数组。
+
+| 方法 | 作用 | 参数 |
+| ----------- | ------------------------------------------ | ----------- |
+| hasPermi | 验证用户是否具备某权限 | permission |
+| hasPermiOr | 验证用户是否含有指定权限,只需包含其中一个 | permissions |
+| hasPermiAnd | 验证用户是否含有指定权限,必须全部拥有 | permissions |
+| hasRole | 验证用户是否具备某角色 | role |
+| hasRoleOr | 验证用户是否含有指定角色,只需包含其中一个 | roles |
+| hasRoleAnd | roles | roles |
+
+#### modal - 弹窗插件
+
+content是消息内容,option是详细配置。
+
+| 方法 | 作用 | 参数 |
+| ------------ | ------------------------------ | ------- |
+| msg | 消息提示 | content |
+| msgError | 错误消息 | content |
+| msgSuccess | 成功消息 | content |
+| hideMsg | 隐藏消息 | 无 |
+| alert | 弹出提示 | content |
+| confirm | 确认窗体 | content |
+| showToast | 提示信息 | option |
+| loading | 打开遮罩层,需要手动关闭遮罩层 | content |
+| closeLoading | 关闭遮罩层 | 无 |
+
+#### bus - 事件插件
+
+eventName是事件名称,eventFun是事件处理函数,请尽量避免事件插件的使用,请在组件销毁是解绑素有该组件有关的事件,避免产生bug。
+
+| 方法 | 作用 | 参数 |
+| ----- | ------------ | ------------------- |
+| $on | 绑定一个事件 | eventName、eventFun |
+| $off | 解绑一个事件 | eventName |
+| $emit | 触发一个事件 | eventName、...args |
+
+#### socket
+
+设置项enableUUID,是否启用基于uuid的消息处理机制,要求当发送的消息携带uuid字段时,返回的消息也要携带uuid字段。
+
+设置项enableEvent,是否启用基于事件的消息处理机制,要求当希望被事件处理函数处理的消息需要携带event字段。
+
+| 方法 | 作用 | 参数 |
+| --------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| connect | 连接websocke,当连接成功后触发回调函数 | 最简单的用法就是传入{url:"ws://demo"} |
+| send | 发送信息,当uuid不为空且不为false时,当收到
携带相同uuid的消息时触发回调函数,只触发一次。
否则由默认处理函数处理。 | msg消息内容,会被处理成json字符串
uuid唯一标识符,可以手动传入,也可以设置为true
当为true时会自动生成一个uuid并添加到msg中。 |
+| close | 关闭连接,会触发回调函数的内容,不会触发默认
关闭事件的处理函数,也不会修改默认关闭事件的
处理函数。 | 无 |
+| on | 监听事件,当收到携带event的消息时会调用回调函数。 | event事件的名称 |
+| off | 取消监听事件 | |
+| onMessage | 定义默认监听事件 | callback 默认监听事件的处理函数 |
+| onError | 定义异常事件 | callback 默认异常事件的处理函数 |
+| onClose | 定义关闭事件 | callback 默认关闭事件的处理函数 |
+
# 作者建议
-plugins下面的tab、auth、modal已经打了上详细的注释文档,使用代码提示的时候应该可以直接看到。
-
-tab: 用于页面的跳转和页面间通讯
-
-auth: 用于鉴权操作
-
-modal: 用于弹窗
-
### 对于选项式
```js
diff --git a/src/App.vue b/src/App.vue
index 5dc2780..7fdaed2 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -2,6 +2,19 @@
export default {
onLaunch: function () {
console.log('App Launch')
+ this.$socket.connect({ url: "ws://127.0.0.1:8080/sc" }).then(res => {
+ console.log("success");
+ this.$socket.onMessage(res => {
+ console.log("onmessage",res);
+ })
+ this.$socket.on("on").then(res=>{
+ console.log("on",res);
+ })
+ this.$socket.send({msg:"xxx"},true).then(res=>{
+ console.log("callback-uuid",res);
+ })
+ this.$socket.send({event:"on"})
+ })
},
onShow: function () {
console.log('App Show')
diff --git a/src/plugins/index.ts b/src/plugins/index.ts
index de429c2..77ac40b 100644
--- a/src/plugins/index.ts
+++ b/src/plugins/index.ts
@@ -2,6 +2,7 @@ import Tab from './tab'
import Auth from './auth'
import Modal from './modal'
import Bus from './bus';
+import Socket from './socket'
import { App } from 'vue';
@@ -9,6 +10,7 @@ export const tab = Tab;
export const auth = Auth;
export const modal = Modal;
export const bus = Bus
+export const socket = Socket
/**
* 在组合式API中可以通过 import { tab, auth, modal } form '@/plugins' 来使用tab、auth、modal
@@ -20,5 +22,6 @@ export default {
app.config.globalProperties.$auth = auth
app.config.globalProperties.$modal = modal
app.config.globalProperties.$bus = bus
+ app.config.globalProperties.$socket = socket
}
}
diff --git a/src/plugins/socket.ts b/src/plugins/socket.ts
new file mode 100644
index 0000000..43ed0e0
--- /dev/null
+++ b/src/plugins/socket.ts
@@ -0,0 +1,131 @@
+import { getToken } from '@/utils/auth'
+import { generateUUID } from '@/utils/geek';
+let _socket: UniApp.SocketTask;
+let _callback: { [key: string]: (data: any) => void } = {}
+const enableUUID = true // 需要接收信息中包含uuid字段,uuid优先级高于event
+const enableEvent = true // 需要接收信息中包含event字段
+
+interface ConnectSocketOption extends UniApp.ConnectSocketOption {
+ headers: {
+ isToken: boolean
+ }
+}
+
+export default {
+ /**
+ * 连接websocket
+ * 最简单的用法就是传入{url:"ws://demo"}
+ * 当连接成功后触发回调函数
+ */
+ connect(options: ConnectSocketOption) {
+ return new Promise((resolve, reject) => {
+ const isToken = (options.headers || {}).isToken === false
+ options.header = options.header || { 'content-type': 'application/json' }
+ if (getToken() && !isToken) {
+ options.header['Authorization'] = 'Bearer ' + getToken()
+ }
+ _socket = uni.connectSocket({
+ url: options.url,
+ header: options.header,
+ method: options.method || 'GET',
+ fail: reject
+ });
+ _socket.onError(reject)
+ _socket.onOpen(resolve)
+ _socket.onMessage(res => {
+ let data = JSON.parse((res || {}).data)
+ if (enableUUID && (data || {}).uuid !== undefined) {
+ _callback[data.uuid](data)
+ } else if (enableEvent && (data || {}).event !== undefined) {
+ _callback[data.event](data)
+ }
+ })
+ })
+ },
+ /**
+ * 发送信息
+ * @param msg 消息,会被处理成json字符串
+ * @param uuid 唯一标识,可以传入uuid,也可以传入true自动生成uuid,flase表示该消息不需要单独处理
+ * @returns
+ */
+ send(msg: any, uuid: string | boolean = false) {
+ return new Promise((resolve, reject) => {
+ if (enableUUID && uuid != undefined && uuid != "" && uuid != false) {
+ if (uuid == true) {
+ msg.uuid = generateUUID()
+ _callback[msg.uuid] = resolve
+ } else {
+ _callback[uuid] = resolve
+ }
+ }
+ _socket.send({
+ data: JSON.stringify(msg),
+ fail: reject
+ })
+ })
+ },
+ /**
+ * 关闭连接
+ * @returns 关闭连接的Promise,回调函数只会运行一次
+ */
+ close() {
+ return new Promise((resolve, reject) => {
+ _socket.close({
+ fail: reject
+ })
+ let onclose = _socket.onClose
+ _socket.onClose(res => {
+ resolve(res)
+ _socket.onClose(onclose)
+ })
+ })
+ },
+ /**
+ * 监听事件
+ * @param event 要监听的事件
+ * @returns 在回调函数中处理事件
+ */
+ on(event: string) {
+ return new Promise((resolve) => {
+ _callback[event] = resolve
+ })
+ },
+ /**
+ * 取消监听事件
+ * @param event 要取消监听的事件
+ */
+ off(event: string) {
+ delete _callback[event]
+ },
+ /**
+ * 定义默认监听事件
+ * @param callback 默认监听事件的处理函数
+ */
+ onMessage(callback: (data: any) => void) {
+ _socket.onMessage(res => {
+ let data = JSON.parse((res || {}).data)
+ if (enableUUID && (data || {}).uuid !== undefined) {
+ _callback[data.uuid](res)
+ delete _callback[data.uuid]
+ } else if (enableEvent && (data || {}).event !== undefined) {
+ _callback[data.event](res)
+ } else {
+ callback(data)
+ }
+ })
+ },
+ /**
+ * 定义异常事件
+ * @param callback 默认异常事件的处理函数
+ */
+ onError(callback: (data: any) => void) {
+ _socket.onError(callback)
+ },
+ /**
+ * 定义关闭事件
+ * @param callback 默认关闭事件的处理函数
+ */
+ onClose(callback: (data: any) => void) {
+ _socket.onError(callback)
+ }
+};
\ No newline at end of file
diff --git a/src/utils/geek.ts b/src/utils/geek.ts
index 53c1eb7..472fa32 100644
--- a/src/utils/geek.ts
+++ b/src/utils/geek.ts
@@ -55,4 +55,22 @@ export function deepCloneTo(obj: T, result: T) {
result[key] = deepClone(value);
}
return result;
-}
\ No newline at end of file
+}
+
+/**
+ * 获取uuid
+ * @returns 生成的uuid字符串
+ */
+export function generateUUID(): string {
+ let uuid = '';
+ const chars = '0123456789abcdef';
+
+ for (let i = 0; i < 32; i++) {
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
+ uuid += '-';
+ }
+ uuid += chars[Math.floor(Math.random() * chars.length)];
+ }
+
+ return uuid;
+ }
\ No newline at end of file