qlfy-postmate 1.1.8 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -226
- package/lib/index.mjs +51 -26
- package/lib/index.mjs.gz +0 -0
- package/lib/index.umd.js +1 -1
- package/lib/postMeta/ChildPostmate.d.ts +1 -1
- package/lib/postMeta/ParentPostmate.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,208 +1,51 @@
|
|
|
1
|
-
### 子系统认证通信插件使用文档
|
|
1
|
+
### 子系统认证通信插件使用文档1.2.0
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
### 【1.2.0优化升级说明】
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
```js
|
|
12
|
-
import { ChildPostmate } from 'qlfy-postmate'
|
|
13
|
-
```
|
|
5
|
+
```txt
|
|
6
|
+
1、优化了同IP链接切换时的系统资源重复加载问题
|
|
7
|
+
增加了系统间的通信处理方式
|
|
8
|
+
新版本中在new ChildPostmate时需传入第二个参数【vue-router的实例对象】router;
|
|
9
|
+
通过通信支持 + ChildPostmate内部对router的操作,实现主系统操控集成系统页面跳转的功能;
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
2、老版本的兼容性支持
|
|
12
|
+
如已完成集成的系统仍使用旧版本插件,集成效果不变,仅性能和切换效果差于新版
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
success: (success: any) => {
|
|
24
|
-
console.log('-----------------链接成功-----------------', success)
|
|
25
|
-
},
|
|
26
|
-
receive: (dataInfo: any) => {
|
|
27
|
-
console.log('-----------------接收数据-----------------', dataInfo)
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
// 带路由功能的使用(推荐)
|
|
32
|
-
import { useRouter } from 'vue-router'
|
|
33
|
-
|
|
34
|
-
const router = useRouter()
|
|
35
|
-
const childrenComm = new ChildPostmate({
|
|
36
|
-
error: (err: any) => {
|
|
37
|
-
console.log('-----------------链接失败-----------------', err)
|
|
38
|
-
},
|
|
39
|
-
success: (success: any) => {
|
|
40
|
-
console.log('-----------------链接成功-----------------', success)
|
|
41
|
-
},
|
|
42
|
-
receive: (dataInfo: any) => {
|
|
43
|
-
console.log('-----------------接收数据-----------------', dataInfo)
|
|
44
|
-
},
|
|
45
|
-
}, router) // 传入router实例,支持路由更新功能
|
|
14
|
+
3、建议
|
|
15
|
+
已完成集成系统也建议使用最新版本,使用变化极小
|
|
16
|
+
仅需以下两步操作:
|
|
17
|
+
(1)下载新版本插件:npm i qlfy-postmate@1.2.0
|
|
18
|
+
(2)使用处添加新参数:router
|
|
19
|
+
new ChildPostmate({...保持不变}, router)
|
|
46
20
|
```
|
|
47
21
|
|
|
48
|
-
#### 4、参数对象说明
|
|
49
|
-
|
|
50
|
-
| 回调函数名称 | 解释 | 回调参数 | 返回值 |
|
|
51
|
-
| ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------ |
|
|
52
|
-
| error | 链接失败、未链接时执行 | null | void |
|
|
53
|
-
| success | 链接成功时执行 | chldPostmate | void |
|
|
54
|
-
| receive | 父页面推送数据时执行,初次链接成功会触发一次<br />可将本回调函数看做为websoket服务,后续父页面可能会不定时向子系统推送数据 | {<br />isHideHeader:boolean,<br />token:string,<br />loginInfo:object,<br />......<br />} | void |
|
|
55
|
-
|
|
56
|
-
#### 5、方法
|
|
57
|
-
|
|
58
|
-
| 名称 | 解释 | 使用 |
|
|
59
|
-
| ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
|
60
|
-
| getData | 链接成功后<br />可通过ChildPostmate实例对象,主动向父页面获取数据 | getData((dataInfo)=>void) |
|
|
61
|
-
| setRouter | 设置Vue Router实例和自定义路由更新回调函数<br />用于在实例创建后设置或更新路由实例 | setRouter(router, [routeUpdateCallback]) |
|
|
62
|
-
| sendOtherRequest | 向父页面发送自定义请求 | sendOtherRequest(params) |
|
|
63
|
-
|
|
64
|
-
#### 注意:
|
|
65
|
-
|
|
66
|
-
1、ChildPostmate 链接的创建是异步过程,需等待error或success函数执行后才可进行登陆状态的判断
|
|
67
|
-
|
|
68
|
-
2、getData方法,仅能在链接创建完成后再调用
|
|
69
|
-
|
|
70
|
-
3、路由更新功能需要传入Vue Router实例才能使用
|
|
71
|
-
|
|
72
|
-
4、路由更新功能会自动判断URL变化类型:
|
|
73
|
-
- 如果只有查询参数或哈希变化,只更新参数,不刷新页面
|
|
74
|
-
- 如果路径变化,会更新整个路由路径,但不会刷新页面
|
|
75
|
-
- 如果协议、主机或端口变化,会重新加载iframe
|
|
76
|
-
|
|
77
|
-
5、如果需要自定义路由更新逻辑,可以传入routeUpdateCallback回调函数
|
|
78
|
-
|
|
79
|
-
6、error、success函数仅作为链接状态的标注函数,不传递数据
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
### 接入步骤
|
|
84
|
-
|
|
85
|
-
1. 对系统登录状态进行改造,系统加载时先将登陆状态判断屏蔽
|
|
86
|
-
|
|
87
|
-
2. 系统公共部分(app.vue)对该插件进行导入和 new,创建实例,并传入相应回调
|
|
88
|
-
|
|
89
|
-
3. 等待回调被执行,并做出以下操作:
|
|
90
|
-
|
|
91
|
-
------- 如果error回调执行:解除对登录状态的屏蔽,走系统本身登陆逻辑;
|
|
92
22
|
|
|
93
|
-
------- 如果success回调执行:
|
|
94
23
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
2、receive回调执行:
|
|
98
|
-
|
|
99
|
-
(1)使用接收数据中的token、loginInfo数据,将本地的登陆状态设置为已登录,后续接口请求时携带本回调传入的token;
|
|
100
|
-
|
|
101
|
-
(2)使用接收数据中的isHideHeader字段,对系统页头的显隐进行控制
|
|
102
|
-
|
|
103
|
-
```vue
|
|
104
|
-
<my-header v-if="!isHideHeader" />
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
(3)解除对登陆状态判断的屏蔽(因已使用接收的数据配置了登录状态,不会触发本系统的登陆);
|
|
108
|
-
|
|
109
|
-
接入步骤(动态路由)
|
|
110
|
-
|
|
111
|
-
### 样例一(app.vue):
|
|
112
|
-
|
|
113
|
-
App.vue
|
|
114
|
-
|
|
115
|
-
```vue
|
|
116
|
-
<template>
|
|
117
|
-
<div class="system-content" v-loading="loading">
|
|
118
|
-
<!-- 系统登录状态的判断,需等待postmate链接的响应后再执行 -->
|
|
119
|
-
|
|
120
|
-
<!-- 页头 -->
|
|
121
|
-
<my-header v-if="!isHideHeader"></my-header>
|
|
24
|
+
#### 1、安装
|
|
122
25
|
|
|
123
|
-
|
|
124
|
-
|
|
26
|
+
```
|
|
27
|
+
npm i qlfy-postmate
|
|
28
|
+
```
|
|
125
29
|
|
|
126
|
-
|
|
127
|
-
<RouterView v-if="!loading" />
|
|
128
|
-
</div>
|
|
129
|
-
</template>
|
|
30
|
+
#### 2、导入
|
|
130
31
|
|
|
131
|
-
|
|
132
|
-
import { ref } from 'vue'
|
|
133
|
-
import { useRouter } from 'vue-router'
|
|
134
|
-
import { useSystemStore } from '@/store/modules/system'
|
|
32
|
+
```js
|
|
135
33
|
import { ChildPostmate } from 'qlfy-postmate'
|
|
136
|
-
|
|
137
|
-
// 系统loading
|
|
138
|
-
const loading = ref(false)
|
|
139
|
-
// 页头是否展示
|
|
140
|
-
const isHideHeader = ref(false)
|
|
141
|
-
// pinia系统数据管理对象
|
|
142
|
-
const systemStore = useSystemStore()
|
|
143
|
-
|
|
144
|
-
initPostMate()
|
|
145
|
-
|
|
146
|
-
// 方法 -- 初始化postmate链接
|
|
147
|
-
function initPostMate() {
|
|
148
|
-
loading.value = true
|
|
149
|
-
// 获取router实例
|
|
150
|
-
const router = useRouter()
|
|
151
|
-
|
|
152
|
-
const childrenComm = new ChildPostmate({
|
|
153
|
-
error: (err: any) => {
|
|
154
|
-
console.log('-----------------链接失败-----------------')
|
|
155
|
-
console.log(err)
|
|
156
|
-
loading.value = false
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
success: (success: any) => {
|
|
160
|
-
console.log('-----------------链接成功-----------------')
|
|
161
|
-
console.log(success)
|
|
162
|
-
loading.value = false
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
receive: (dataInfo: any) => {
|
|
166
|
-
console.log('-----------------接收数据-----------------')
|
|
167
|
-
console.log(dataInfo)
|
|
168
|
-
if (dataInfo.status !== 200) return
|
|
169
|
-
/**
|
|
170
|
-
* 接收到推送数据后做如下操作
|
|
171
|
-
* 1、根据isHideHeader控制页头显隐
|
|
172
|
-
* 2、将登录装填变更为已登录,并将token保存在正常登录所在位置进行取用
|
|
173
|
-
*/
|
|
174
|
-
|
|
175
|
-
// 控制导航、页头的展示
|
|
176
|
-
isHideHeader.value = dataInfo.data.isHideHeader
|
|
177
|
-
// 保存登陆信息
|
|
178
|
-
systemStore.setLoginInfo(dataInfo.data.loginInfo)
|
|
179
|
-
// 保存token
|
|
180
|
-
systemStore.setTooken(dataInfo.data.token)
|
|
181
|
-
},
|
|
182
|
-
}, router) // 传入router实例,支持路由更新功能
|
|
183
|
-
}
|
|
184
|
-
</script>
|
|
185
|
-
|
|
186
|
-
<style scoped></style>
|
|
187
|
-
|
|
188
34
|
```
|
|
189
35
|
|
|
190
|
-
|
|
36
|
+
#### 3、使用(main.js)
|
|
191
37
|
|
|
192
38
|
```js
|
|
193
39
|
import { createApp } from "vue";
|
|
194
40
|
import App from "./App.vue";
|
|
195
|
-
import { ChildPostmate } from 'qlfy-postmate'
|
|
196
41
|
import router from "./router";
|
|
197
|
-
|
|
198
42
|
import { createPinia } from "pinia";
|
|
43
|
+
import { ChildPostmate } from 'qlfy-postmate'
|
|
199
44
|
const store = createPinia(); //pinia实例
|
|
200
|
-
|
|
45
|
+
const app = createApp(App);
|
|
201
46
|
|
|
202
47
|
// pinia
|
|
203
48
|
app.use(store);
|
|
204
|
-
// 路由拦截器
|
|
205
|
-
import '@/permission.js'
|
|
206
49
|
|
|
207
50
|
// 标识,是否为首次加载项目
|
|
208
51
|
let flag = true
|
|
@@ -229,10 +72,10 @@ new ChildPostmate({
|
|
|
229
72
|
|
|
230
73
|
// 数据更新 -- 是否隐藏页头
|
|
231
74
|
$store.setIsHideHeader(dataInfo.data.isHideHeader);
|
|
75
|
+
// 数据更新 -- token
|
|
76
|
+
$store.setToken(dataInfo.data.token);
|
|
232
77
|
// 数据更新 -- 登陆信息
|
|
233
78
|
$store.setLoginInfo(dataInfo.data.loginInfo);
|
|
234
|
-
localStorage.setItem('info', JSON.stringify(dataInfo.data.loginInfo));
|
|
235
|
-
|
|
236
79
|
// 项目挂载,仅首次加载项目时执行,后续receive触发不执行
|
|
237
80
|
if (flag) {
|
|
238
81
|
app.use(router)
|
|
@@ -243,61 +86,42 @@ new ChildPostmate({
|
|
|
243
86
|
}, router) // 传入router实例,支持路由更新功能
|
|
244
87
|
```
|
|
245
88
|
|
|
89
|
+
#### 4、参数说明
|
|
246
90
|
|
|
91
|
+
| 参数名 | 说明 | 类型 |
|
|
92
|
+
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
|
93
|
+
| eventObj | 事件对象集,对外暴露链接状态<br />详细说明见下方eventObj说明 | {<br />error:()=>void<br />success:(childPostmate)=>viod<br />receive:(res:any)=>void<br />} |
|
|
94
|
+
| router | 当前系统的vue-router实例 | Router |
|
|
247
95
|
|
|
248
|
-
|
|
96
|
+
#### eventObj说明
|
|
249
97
|
|
|
250
|
-
|
|
98
|
+
| 属性(支持的事件回调) | 说明 | 类型 |
|
|
99
|
+
| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
|
100
|
+
| error | 链接失败、未链接时执行 | ()=>void |
|
|
101
|
+
| success | 链接成功时执行 | (chldPostmate)=>void |
|
|
102
|
+
| receive | 父页面推送数据时执行,初次链接成功会触发一次<br />可将本回调函数看做为websoket服务,<br />后续父页面可能会不定时向子系统推送数据 | (<br /> {<br /> isHideHeader:boolean,<br /> token:string,<br /> loginInfo:object,<br /> ......<br /> }<br />)=>void |
|
|
251
103
|
|
|
252
|
-
```js
|
|
253
|
-
import { ParentPostmate } from 'qlfy-postmate'
|
|
254
|
-
```
|
|
255
104
|
|
|
256
|
-
#### 2、基本使用
|
|
257
105
|
|
|
258
|
-
|
|
259
|
-
// 创建父页面通信实例
|
|
260
|
-
const parentComm = new ParentPostmate(
|
|
261
|
-
// 传递给子页面的数据
|
|
262
|
-
{
|
|
263
|
-
loginInfo: { /* 登录信息 */ },
|
|
264
|
-
token: 'token字符串',
|
|
265
|
-
isHideHeader: true
|
|
266
|
-
},
|
|
267
|
-
// iframe容器元素
|
|
268
|
-
document.getElementById('iframe-container'),
|
|
269
|
-
// 子页面URL
|
|
270
|
-
'http://example.com/child-page',
|
|
271
|
-
// 处理子页面其他请求的回调函数
|
|
272
|
-
(params) => {
|
|
273
|
-
console.log('收到子页面请求:', params)
|
|
274
|
-
}
|
|
275
|
-
)
|
|
276
|
-
```
|
|
106
|
+
#### 5、方法
|
|
277
107
|
|
|
278
|
-
|
|
108
|
+
| 名称 | 说明 | 使用 |
|
|
109
|
+
| ---------------- | ------------------------------------------------------------ | ---------------------------------------- |
|
|
110
|
+
| getData | 链接成功后<br />可通过ChildPostmate实例对象,主动向父页面获取数据 | getData((dataInfo)=>void) |
|
|
111
|
+
| setRouter | 设置Vue Router实例和自定义路由更新回调函数<br />用于在实例创建后设置或更新路由实例 | setRouter(router, [routeUpdateCallback]) |
|
|
112
|
+
| sendOtherRequest | 向父页面发送自定义请求 | sendOtherRequest(params) |
|
|
279
113
|
|
|
280
|
-
|
|
114
|
+
#### 注意:
|
|
281
115
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
```
|
|
116
|
+
1、ChildPostmate 链接的创建是异步过程,需等待error或success函数执行后才可进行登陆状态的判断
|
|
117
|
+
|
|
118
|
+
2、getData方法,仅能在链接创建完成后再调用
|
|
286
119
|
|
|
287
|
-
|
|
288
|
-
- 如果只有查询参数或哈希变化,只更新参数,不刷新页面
|
|
289
|
-
- 如果路径变化,会更新整个路由路径,但不会刷新页面
|
|
290
|
-
- 如果协议、主机或端口变化,会重新加载iframe
|
|
120
|
+
3、路由更新功能需要传入Vue Router实例才能使用
|
|
291
121
|
|
|
292
|
-
|
|
122
|
+
5、如果需要自定义路由更新逻辑,可以传入routeUpdateCallback回调函数
|
|
293
123
|
|
|
294
|
-
|
|
295
|
-
| ------ | ---- | ---- |
|
|
296
|
-
| setIframeUrl | 设置iframe的URL | (url: string) |
|
|
297
|
-
| setIframeEle | 设置iframe容器元素 | (element: HTMLElement \| (() => HTMLElement)) |
|
|
298
|
-
| sendData | 向子页面发送数据 | () |
|
|
299
|
-
| setLoadFunction | 设置iframe加载完成的回调函数 | (callback: () => void) |
|
|
300
|
-
| destroy | 销毁实例 | () |
|
|
124
|
+
6、error、success函数仅作为链接状态的标注函数,不传递数据
|
|
301
125
|
|
|
302
126
|
### 集成调试
|
|
303
127
|
|
package/lib/index.mjs
CHANGED
|
@@ -8,13 +8,13 @@ const f = {
|
|
|
8
8
|
reply: 1,
|
|
9
9
|
request: 1
|
|
10
10
|
};
|
|
11
|
-
function
|
|
11
|
+
function u(n, t) {
|
|
12
12
|
return (typeof t != "string" || n.origin === t) && !!n.data && (typeof n.data != "object" || "postmate" in n.data) && n.data.type === c && !!f[n.data.postmate];
|
|
13
13
|
}
|
|
14
14
|
class g {
|
|
15
15
|
constructor(t) {
|
|
16
16
|
this.parent = t.parent, this.frame = t.frame, this.child = t.child, this.childOrigin = t.childOrigin, this.events = {}, this.listener = (e) => {
|
|
17
|
-
if (!
|
|
17
|
+
if (!u(e, this.childOrigin)) return;
|
|
18
18
|
const { value: s = {} } = e.data, { name: a, data: r } = s;
|
|
19
19
|
e.data.postmate === "emit" && a in this.events && this.events[a].call(this, r);
|
|
20
20
|
}, this.parent.addEventListener("message", this.listener, !1);
|
|
@@ -53,10 +53,10 @@ class g {
|
|
|
53
53
|
window.removeEventListener("message", this.listener, !1), this.frame.parentNode.removeChild(this.frame);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
class
|
|
56
|
+
class w {
|
|
57
57
|
constructor(t) {
|
|
58
58
|
this.model = t.model, this.parent = t.parent, this.parentOrigin = t.parentOrigin, this.child = t.child, this.child.addEventListener("message", (e) => {
|
|
59
|
-
if (!
|
|
59
|
+
if (!u(e, this.parentOrigin)) return;
|
|
60
60
|
const { postmate: s, property: a, uid: r, data: h } = e.data, i = this.model[a];
|
|
61
61
|
if (s !== "call") {
|
|
62
62
|
const l = typeof i == "function" ? i() : i;
|
|
@@ -99,9 +99,9 @@ class o {
|
|
|
99
99
|
})();
|
|
100
100
|
let s = 0, a;
|
|
101
101
|
return new o.Promise((r, h) => {
|
|
102
|
-
const i = (
|
|
103
|
-
if (!p
|
|
104
|
-
|
|
102
|
+
const i = (p) => {
|
|
103
|
+
if (!u(p, e)) return !1;
|
|
104
|
+
p.data.postmate === "handshake-reply" ? (clearInterval(a), this.parent.removeEventListener("message", i, !1), this.childOrigin = p.origin, r(new g(this))) : h("Failed handshake");
|
|
105
105
|
};
|
|
106
106
|
this.parent.addEventListener("message", i, !1);
|
|
107
107
|
const l = () => {
|
|
@@ -120,7 +120,7 @@ class o {
|
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
class
|
|
123
|
+
class P {
|
|
124
124
|
constructor(t) {
|
|
125
125
|
return this.child = window, this.model = t, this.parent = window.parent, this.sendHandshakeReply();
|
|
126
126
|
}
|
|
@@ -139,7 +139,7 @@ class y {
|
|
|
139
139
|
const a = s.data.model;
|
|
140
140
|
a && Object.keys(a).forEach((r) => {
|
|
141
141
|
this.model[r] = a[r];
|
|
142
|
-
}), t(new
|
|
142
|
+
}), t(new w(this));
|
|
143
143
|
}
|
|
144
144
|
}, !1);
|
|
145
145
|
});
|
|
@@ -153,8 +153,8 @@ o.Promise = (() => {
|
|
|
153
153
|
return Promise;
|
|
154
154
|
}
|
|
155
155
|
})();
|
|
156
|
-
o.Model =
|
|
157
|
-
class
|
|
156
|
+
o.Model = P;
|
|
157
|
+
class y {
|
|
158
158
|
constructor(t, e, s) {
|
|
159
159
|
this.childPostmate = null, this.parentPostmate = null, this.isGetData = !1, this.getDataCllBack = null, this.router = null, this.routeUpdateCallback = null, this.router = e, this.routeUpdateCallback = s, window.top !== window.self ? this.init(t) : t.error({ status: 500, data: null, message: "未在一体化平台中运行" });
|
|
160
160
|
}
|
|
@@ -176,6 +176,10 @@ class w {
|
|
|
176
176
|
// 处理路由更新
|
|
177
177
|
routeUpdate(s) {
|
|
178
178
|
try {
|
|
179
|
+
window.parent.postMessage(JSON.stringify({
|
|
180
|
+
type: "route_update_support",
|
|
181
|
+
supported: !0
|
|
182
|
+
}), "*");
|
|
179
183
|
const a = JSON.parse(s);
|
|
180
184
|
if (e.routeUpdateCallback) {
|
|
181
185
|
e.routeUpdateCallback(a);
|
|
@@ -232,13 +236,13 @@ class U {
|
|
|
232
236
|
loginInfo: {},
|
|
233
237
|
token: "",
|
|
234
238
|
isHideHeader: !0
|
|
235
|
-
}, this.iframeEle = null, this.currentUrl = "", this.currentIframe = null, this.loadFunction = null, this.handleOtherRequest = null, this.parsedCurrentUrl = null, this.dataInfo = t || this.dataInfo, this.iframeEle = e, this.setIframeUrl(s), a && (this.handleOtherRequest = a);
|
|
239
|
+
}, this.iframeEle = null, this.currentUrl = "", this.currentIframe = null, this.loadFunction = null, this.handleOtherRequest = null, this.parsedCurrentUrl = null, this.childSupportsRouteUpdate = !0, this.dataInfo = t || this.dataInfo, this.iframeEle = e, this.setIframeUrl(s), a && (this.handleOtherRequest = a);
|
|
236
240
|
}
|
|
237
241
|
/** 解析URL */
|
|
238
242
|
parseUrl(t) {
|
|
239
243
|
const e = document.createElement("a");
|
|
240
244
|
e.href = t;
|
|
241
|
-
const s = e.protocol.length > 4 ? e.protocol : window.location.protocol, a = e.hostname, r = e.port || (s === "https:" ? "443" : s === "http:" ? "80" : ""), h = e.pathname.startsWith("/") ? e.pathname : `/${e.pathname}`, i = e.search, l = e.hash, d = e.origin || `${s}//${a}${r ? `:${r}` : ""}`,
|
|
245
|
+
const s = e.protocol.length > 4 ? e.protocol : window.location.protocol, a = e.hostname, r = e.port || (s === "https:" ? "443" : s === "http:" ? "80" : ""), h = e.pathname.startsWith("/") ? e.pathname : `/${e.pathname}`, i = e.search, l = e.hash, d = e.origin || `${s}//${a}${r ? `:${r}` : ""}`, p = `${h}${i}${l}`;
|
|
242
246
|
return {
|
|
243
247
|
protocol: s,
|
|
244
248
|
host: a,
|
|
@@ -247,7 +251,7 @@ class U {
|
|
|
247
251
|
search: i,
|
|
248
252
|
hash: l,
|
|
249
253
|
origin: d,
|
|
250
|
-
fullPath:
|
|
254
|
+
fullPath: p
|
|
251
255
|
};
|
|
252
256
|
}
|
|
253
257
|
/** 比较两个URL是否相同(协议、主机、端口) */
|
|
@@ -274,7 +278,7 @@ class U {
|
|
|
274
278
|
}
|
|
275
279
|
/** 初始化 */
|
|
276
280
|
async init(t = null) {
|
|
277
|
-
if (this.clear(), !this.iframeEle || !this.currentUrl) {
|
|
281
|
+
if (this.clear(), this.childSupportsRouteUpdate = !0, !this.iframeEle || !this.currentUrl) {
|
|
278
282
|
console.warn("iframeEle 和 currentUrl 是必需的");
|
|
279
283
|
return;
|
|
280
284
|
}
|
|
@@ -313,7 +317,7 @@ class U {
|
|
|
313
317
|
return;
|
|
314
318
|
}
|
|
315
319
|
const e = this.parseUrl(t);
|
|
316
|
-
if (this.postmateParent && this.compareUrlBase(this.currentUrl, t))
|
|
320
|
+
if (this.postmateParent && this.compareUrlBase(this.currentUrl, t) && this.childSupportsRouteUpdate)
|
|
317
321
|
if (this.compareUrlPath(this.currentUrl, t)) {
|
|
318
322
|
if (this.compareUrlFull(this.currentUrl, t))
|
|
319
323
|
return;
|
|
@@ -327,15 +331,36 @@ class U {
|
|
|
327
331
|
}
|
|
328
332
|
/** 向子页面发送路由更新消息 */
|
|
329
333
|
sendRouteUpdate(t) {
|
|
330
|
-
this.postmateParent
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
334
|
+
if (this.postmateParent) {
|
|
335
|
+
if (!this.childSupportsRouteUpdate) {
|
|
336
|
+
console.warn("子页面不支持路由更新,直接重新初始化iframe"), this.init();
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
this.postmateParent.call(
|
|
341
|
+
"routeUpdate",
|
|
342
|
+
JSON.stringify({
|
|
343
|
+
fullPath: t.fullPath,
|
|
344
|
+
pathname: t.pathname,
|
|
345
|
+
search: t.search,
|
|
346
|
+
hash: t.hash
|
|
347
|
+
})
|
|
348
|
+
);
|
|
349
|
+
let e = !1;
|
|
350
|
+
const s = (a) => {
|
|
351
|
+
try {
|
|
352
|
+
const r = JSON.parse(a.data);
|
|
353
|
+
r && r.type === "route_update_support" && r.supported === !0 && (e = !0, window.removeEventListener("message", s));
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
window.addEventListener("message", s), setTimeout(() => {
|
|
358
|
+
window.removeEventListener("message", s), e || (console.warn("子页面不支持路由更新,将在下次更新时重新初始化iframe"), this.childSupportsRouteUpdate = !1, this.init());
|
|
359
|
+
}, 1e3);
|
|
360
|
+
} catch (e) {
|
|
361
|
+
console.warn("发送路由更新消息失败,将重新初始化iframe:", e), this.childSupportsRouteUpdate = !1, this.init();
|
|
362
|
+
}
|
|
363
|
+
}
|
|
339
364
|
}
|
|
340
365
|
/** 向子页面发送消息 */
|
|
341
366
|
sendData() {
|
|
@@ -347,6 +372,6 @@ class U {
|
|
|
347
372
|
}
|
|
348
373
|
}
|
|
349
374
|
export {
|
|
350
|
-
|
|
375
|
+
y as ChildPostmate,
|
|
351
376
|
U as ParentPostmate
|
|
352
377
|
};
|
package/lib/index.mjs.gz
CHANGED
|
Binary file
|
package/lib/index.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(d,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(d=typeof globalThis<"u"?globalThis:d||self,n(d["qlfy-postmate"]={}))})(this,function(d){"use strict";const n="application/x-postmate-v1+json";let f=0;const g={handshake:1,"handshake-reply":1,call:1,emit:1,reply:1,request:1};function m(o,t){return(typeof t!="string"||o.origin===t)&&!!o.data&&(typeof o.data!="object"||"postmate"in o.data)&&o.data.type===n&&!!g[o.data.postmate]}class P{constructor(t){this.parent=t.parent,this.frame=t.frame,this.child=t.child,this.childOrigin=t.childOrigin,this.events={},this.listener=e=>{if(!m(e,this.childOrigin))return;const{value:s={}}=e.data,{name:a,data:r}=s;e.data.postmate==="emit"&&a in this.events&&this.events[a].call(this,r)},this.parent.addEventListener("message",this.listener,!1)}get(t){return new h.Promise(e=>{const s=++f,a=r=>{r.data.uid===s&&r.data.postmate==="reply"&&(this.parent.removeEventListener("message",a,!1),e(r.data.value))};this.parent.addEventListener("message",a,!1),this.child.postMessage({postmate:"request",type:n,property:t,uid:s},this.childOrigin)})}call(t,e){this.child.postMessage({postmate:"call",type:n,property:t,data:e},this.childOrigin)}on(t,e){this.events[t]=e}destroy(){window.removeEventListener("message",this.listener,!1),this.frame.parentNode.removeChild(this.frame)}}class w{constructor(t){this.model=t.model,this.parent=t.parent,this.parentOrigin=t.parentOrigin,this.child=t.child,this.child.addEventListener("message",e=>{if(!m(e,this.parentOrigin))return;const{postmate:s,property:a,uid:r,data:l}=e.data,i=this.model[a];if(s!=="call"){const c=typeof i=="function"?i():i;h.Promise.resolve(c).then(u=>{e.source.postMessage({property:a,postmate:"reply",type:n,uid:r,value:u},e.origin)})}else a in this.model&&typeof i=="function"&&i(l)})}emit(t,e){this.parent.postMessage({postmate:"emit",type:n,value:{name:t,data:e}},this.parentOrigin)}}class h{constructor({container:t=document.body,model:e,url:s,name:a,classListArray:r=[]}){return this.parent=window,this.frame=document.createElement("iframe"),this.frame.name=a||"",this.frame.classList.add(...r),t.appendChild(this.frame),this.child=this.frame.contentWindow,this.model=e||{},this.sendHandshake(s)}sendHandshake(t){const e=(()=>{const r=document.createElement("a");r.href=t;const l=r.protocol.length>4?r.protocol:window.location.protocol,i=r.host.length?r.port==="80"||r.port==="443"?r.hostname:r.host:window.location.host;return r.origin||`${l}//${i}`})();let s=0,a;return new h.Promise((r,l)=>{const i=p=>{if(!m(p,e))return!1;p.data.postmate==="handshake-reply"?(clearInterval(a),this.parent.removeEventListener("message",i,!1),this.childOrigin=p.origin,r(new P(this))):l("Failed handshake")};this.parent.addEventListener("message",i,!1);const c=()=>{s++,this.child.postMessage({postmate:"handshake",type:n,model:this.model},e),s===5&&clearInterval(a)},u=()=>{c(),a=setInterval(c,500)};this.frame.onload=u,this.frame.attachEvent&&this.frame.attachEvent("onload",u),this.frame.src=t})}}class y{constructor(t){return this.child=window,this.model=t,this.parent=window.parent,this.sendHandshakeReply()}sendHandshakeReply(){return new h.Promise((t,e)=>{this.child.addEventListener("message",s=>{if(s.data.postmate){if(s.data.postmate!=="handshake")return e("Handshake Reply Failed");this.child.removeEventListener("message",this,!1),s.source.postMessage({postmate:"handshake-reply",type:n},s.origin),this.parentOrigin=s.origin;const a=s.data.model;a&&Object.keys(a).forEach(r=>{this.model[r]=a[r]}),t(new w(this))}},!1)})}}h.debug=!1,h.Promise=(()=>{try{return typeof window<"u"?window.Promise:Promise}catch{return Promise}})(),h.Model=y;class U{constructor(t,e,s){this.childPostmate=null,this.parentPostmate=null,this.isGetData=!1,this.getDataCllBack=null,this.router=null,this.routeUpdateCallback=null,this.router=e,this.routeUpdateCallback=s,window.top!==window.self?this.init(t):t.error({status:500,data:null,message:"未在一体化平台中运行"})}init(t){const e=this;this.childPostmate=new h.Model({baseData(s){s=JSON.parse(s),e.isGetData?e.getDataCllBack&&e.getDataCllBack({status:200,message:"success",data:s}):t.receive({status:200,message:"success",data:s}),e.isGetData=!1},routeUpdate(s){try{window.parent.postMessage(JSON.stringify({type:"route_update_support",supported:!0}),"*");const a=JSON.parse(s);if(e.routeUpdateCallback){e.routeUpdateCallback(a);return}e.router?e.router.replace(a.fullPath):console.warn("未提供router实例,无法进行路由更新")}catch(a){console.error("路由更新失败:",a)}}}).then(s=>{e.parentPostmate=s,e.getData(),t.success({status:200,message:"success",data:{ChildPostmate:s}})}).catch(s=>{t.error({status:500,data:null,message:s})})}getData(t){if(!this.parentPostmate){t({status:500,message:"父页面未连接",data:null});return}t?(this.isGetData=!0,this.getDataCllBack=t):(this.isGetData=!1,this.getDataCllBack=null),this.parentPostmate.emit("requestBaseData")}setRouter(t,e){this.router=t,e&&(this.routeUpdateCallback=e)}sendOtherRequest(t){this.parentPostmate&&this.parentPostmate.emit("otherRequest",t)}}class E{constructor(t,e,s="",a){this.postmateParent=null,this.dataInfo={loginInfo:{},token:"",isHideHeader:!0},this.iframeEle=null,this.currentUrl="",this.currentIframe=null,this.loadFunction=null,this.handleOtherRequest=null,this.parsedCurrentUrl=null,this.childSupportsRouteUpdate=!0,this.dataInfo=t||this.dataInfo,this.iframeEle=e,this.setIframeUrl(s),a&&(this.handleOtherRequest=a)}parseUrl(t){const e=document.createElement("a");e.href=t;const s=e.protocol.length>4?e.protocol:window.location.protocol,a=e.hostname,r=e.port||(s==="https:"?"443":s==="http:"?"80":""),l=e.pathname.startsWith("/")?e.pathname:`/${e.pathname}`,i=e.search,c=e.hash,u=e.origin||`${s}//${a}${r?`:${r}`:""}`,p=`${l}${i}${c}`;return{protocol:s,host:a,port:r,pathname:l,search:i,hash:c,origin:u,fullPath:p}}compareUrlBase(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.protocol===a.protocol&&s.host===a.host&&s.port===a.port}compareUrlPath(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.pathname===a.pathname}compareUrlFull(t,e){if(!t||!e)return!1;const s=this.parseUrl(t),a=this.parseUrl(e);return s.fullPath===a.fullPath}clear(){this.postmateParent&&(this.postmateParent.destroy(),this.postmateParent=null),this.currentIframe&&this.currentIframe.parentNode&&this.currentIframe.parentNode.removeChild(this.currentIframe),this.currentIframe=null}async init(t=null){if(this.clear(),this.childSupportsRouteUpdate=!0,!this.iframeEle||!this.currentUrl){console.warn("iframeEle 和 currentUrl 是必需的");return}const e=typeof this.iframeEle=="function"?this.iframeEle():this.iframeEle;if(!e){console.warn("无法获取 iframe 容器");return}const s=new h({container:e,url:this.currentUrl,name:"",model:""});this.currentIframe=e.querySelector("iframe"),this.currentIframe.setAttribute("frameborder","0"),this.currentIframe.setAttribute("allow","fullscreen"),this.currentIframe.addEventListener("load",()=>{this.loadFunction&&this.loadFunction()}),s.then(a=>{this.postmateParent=a,a.on("requestBaseData",()=>{this.sendData()}),a.on("otherRequest",r=>{this.handleOtherRequest&&this.handleOtherRequest(r)}),typeof t=="function"&&t()}).catch(a=>{console.error("Postmate 连接失败:",a)})}setLoadFunction(t){this.loadFunction=t}setIframeUrl(t){if(this.currentUrl===t)return;if(!this.currentUrl){this.currentUrl=t,this.parsedCurrentUrl=this.parseUrl(t),this.iframeEle&&this.init();return}const e=this.parseUrl(t);if(this.postmateParent&&this.compareUrlBase(this.currentUrl,t)&&this.childSupportsRouteUpdate)if(this.compareUrlPath(this.currentUrl,t)){if(this.compareUrlFull(this.currentUrl,t))return;this.currentUrl=t,this.parsedCurrentUrl=e,this.sendRouteUpdate(e);return}else{this.currentUrl=t,this.parsedCurrentUrl=e,this.sendRouteUpdate(e);return}this.currentUrl=t,this.parsedCurrentUrl=e,this.iframeEle&&this.init()}sendRouteUpdate(t){if(this.postmateParent){if(!this.childSupportsRouteUpdate){console.warn("子页面不支持路由更新,直接重新初始化iframe"),this.init();return}try{this.postmateParent.call("routeUpdate",JSON.stringify({fullPath:t.fullPath,pathname:t.pathname,search:t.search,hash:t.hash}));let e=!1;const s=a=>{try{const r=JSON.parse(a.data);r&&r.type==="route_update_support"&&r.supported===!0&&(e=!0,window.removeEventListener("message",s))}catch{}};window.addEventListener("message",s),setTimeout(()=>{window.removeEventListener("message",s),e||(console.warn("子页面不支持路由更新,将在下次更新时重新初始化iframe"),this.childSupportsRouteUpdate=!1,this.init())},1e3)}catch(e){console.warn("发送路由更新消息失败,将重新初始化iframe:",e),this.childSupportsRouteUpdate=!1,this.init()}}}sendData(){this.postmateParent&&this.postmateParent.call("baseData",JSON.stringify(this.dataInfo))}destroy(){this.clear()}}d.ChildPostmate=U,d.ParentPostmate=E,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -16,7 +16,7 @@ export default class ChildPostmate {
|
|
|
16
16
|
getDataCllBack: Function | null;
|
|
17
17
|
router: any;
|
|
18
18
|
routeUpdateCallback: ((routeInfo: RouteUpdateInfo) => void) | null;
|
|
19
|
-
constructor(eventObj: EventObj, router
|
|
19
|
+
constructor(eventObj: EventObj, router: any, routeUpdateCallback?: (routeInfo: RouteUpdateInfo) => void);
|
|
20
20
|
init(eventObj: EventObj): void;
|
|
21
21
|
getData(callback?: any): void;
|
|
22
22
|
/**
|
|
@@ -32,6 +32,8 @@ export default class ParentPostmate {
|
|
|
32
32
|
handleOtherRequest: ((params: any) => void) | null;
|
|
33
33
|
/** 当前URL解析结果 */
|
|
34
34
|
parsedCurrentUrl: ParsedUrl | null;
|
|
35
|
+
/** 子页面是否支持路由更新 */
|
|
36
|
+
childSupportsRouteUpdate: boolean;
|
|
35
37
|
constructor(dataInfo: DataInfo, iframeEle: HTMLElement | (() => HTMLElement), iframeUrl?: string, handleOtherRequest?: (params: any) => void);
|
|
36
38
|
/** 解析URL */
|
|
37
39
|
parseUrl(url: string): ParsedUrl;
|