qlfy-postmate 1.1.6 → 1.1.8

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 CHANGED
@@ -14,7 +14,8 @@ import { ChildPostmate } from 'qlfy-postmate'
14
14
 
15
15
  #### 3、使用
16
16
 
17
- ```
17
+ ```js
18
+ // 基本使用
18
19
  const childrenComm = new ChildPostmate({
19
20
  error: (err: any) => {
20
21
  console.log('-----------------链接失败-----------------', err)
@@ -26,6 +27,22 @@ const childrenComm = new ChildPostmate({
26
27
  console.log('-----------------接收数据-----------------', dataInfo)
27
28
  },
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实例,支持路由更新功能
29
46
  ```
30
47
 
31
48
  #### 4、参数对象说明
@@ -38,9 +55,11 @@ const childrenComm = new ChildPostmate({
38
55
 
39
56
  #### 5、方法
40
57
 
41
- | 名称 | 解释 | 使用 |
42
- | ------- | ------------------------------------------------------------ | ------------------------- |
43
- | getData | 链接成功后<br />可通过ChildPostmate实例对象,主动向父页面获取数据 | getData((dataInfo)=>void) |
58
+ | 名称 | 解释 | 使用 |
59
+ | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
60
+ | getData | 链接成功后<br />可通过ChildPostmate实例对象,主动向父页面获取数据 | getData((dataInfo)=>void) |
61
+ | setRouter | 设置Vue Router实例和自定义路由更新回调函数<br />用于在实例创建后设置或更新路由实例 | setRouter(router, [routeUpdateCallback]) |
62
+ | sendOtherRequest | 向父页面发送自定义请求 | sendOtherRequest(params) |
44
63
 
45
64
  #### 注意:
46
65
 
@@ -48,7 +67,16 @@ const childrenComm = new ChildPostmate({
48
67
 
49
68
  2、getData方法,仅能在链接创建完成后再调用
50
69
 
51
- 3、error、success函数仅作为链接状态的标注函数,不传递数据
70
+ 3、路由更新功能需要传入Vue Router实例才能使用
71
+
72
+ 4、路由更新功能会自动判断URL变化类型:
73
+ - 如果只有查询参数或哈希变化,只更新参数,不刷新页面
74
+ - 如果路径变化,会更新整个路由路径,但不会刷新页面
75
+ - 如果协议、主机或端口变化,会重新加载iframe
76
+
77
+ 5、如果需要自定义路由更新逻辑,可以传入routeUpdateCallback回调函数
78
+
79
+ 6、error、success函数仅作为链接状态的标注函数,不传递数据
52
80
 
53
81
 
54
82
 
@@ -102,6 +130,7 @@ App.vue
102
130
 
103
131
  <script setup lang="ts">
104
132
  import { ref } from 'vue'
133
+ import { useRouter } from 'vue-router'
105
134
  import { useSystemStore } from '@/store/modules/system'
106
135
  import { ChildPostmate } from 'qlfy-postmate'
107
136
 
@@ -117,6 +146,9 @@ initPostMate()
117
146
  // 方法 -- 初始化postmate链接
118
147
  function initPostMate() {
119
148
  loading.value = true
149
+ // 获取router实例
150
+ const router = useRouter()
151
+
120
152
  const childrenComm = new ChildPostmate({
121
153
  error: (err: any) => {
122
154
  console.log('-----------------链接失败-----------------')
@@ -147,7 +179,7 @@ function initPostMate() {
147
179
  // 保存token
148
180
  systemStore.setTooken(dataInfo.data.token)
149
181
  },
150
- })
182
+ }, router) // 传入router实例,支持路由更新功能
151
183
  }
152
184
  </script>
153
185
 
@@ -157,8 +189,7 @@ function initPostMate() {
157
189
 
158
190
  ### 样例二(main.js)【推荐】:
159
191
 
160
- ```
161
-
192
+ ```js
162
193
  import { createApp } from "vue";
163
194
  import App from "./App.vue";
164
195
  import { ChildPostmate } from 'qlfy-postmate'
@@ -178,7 +209,7 @@ let flag = true
178
209
  // pinia模块
179
210
  import useCounterStore from "@/store/index.js";
180
211
  const $store = useCounterStore();
181
- // 创建链接
212
+ // 创建链接,传入router实例以支持路由更新功能
182
213
  new ChildPostmate({
183
214
  error: (err) => {
184
215
  console.log('-----------------链接失败-----------------')
@@ -191,7 +222,7 @@ new ChildPostmate({
191
222
  },
192
223
 
193
224
  // 异步方法
194
- receive: async (dataInfo) => {
225
+ receive: (dataInfo) => {
195
226
  console.log('-----------------接收数据-----------------')
196
227
  console.log(dataInfo)
197
228
  if (dataInfo.status !== 200) return
@@ -209,10 +240,64 @@ new ChildPostmate({
209
240
  }
210
241
  flag = false
211
242
  },
212
- })
243
+ }, router) // 传入router实例,支持路由更新功能
244
+ ```
245
+
246
+
247
+
248
+ ### 父页面使用说明(ParentPostmate)
249
+
250
+ #### 1、导入
251
+
252
+ ```js
253
+ import { ParentPostmate } from 'qlfy-postmate'
213
254
  ```
214
255
 
256
+ #### 2、基本使用
257
+
258
+ ```js
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
+ ```
277
+
278
+ #### 3、路由更新功能
279
+
280
+ 当需要更新子页面URL时,只需调用`setIframeUrl`方法:
281
+
282
+ ```js
283
+ // 更新子页面URL
284
+ parentComm.setIframeUrl('http://example.com/child-page/new-route?param=value')
285
+ ```
286
+
287
+ 系统会自动判断URL变化类型:
288
+ - 如果只有查询参数或哈希变化,只更新参数,不刷新页面
289
+ - 如果路径变化,会更新整个路由路径,但不会刷新页面
290
+ - 如果协议、主机或端口变化,会重新加载iframe
291
+
292
+ #### 4、方法说明
215
293
 
294
+ | 方法名 | 说明 | 参数 |
295
+ | ------ | ---- | ---- |
296
+ | setIframeUrl | 设置iframe的URL | (url: string) |
297
+ | setIframeEle | 设置iframe容器元素 | (element: HTMLElement \| (() => HTMLElement)) |
298
+ | sendData | 向子页面发送数据 | () |
299
+ | setLoadFunction | 设置iframe加载完成的回调函数 | (callback: () => void) |
300
+ | destroy | 销毁实例 | () |
216
301
 
217
302
  ### 集成调试
218
303
 
package/lib/index.mjs CHANGED
@@ -1,9 +1,6 @@
1
- var f = Object.defineProperty;
2
- var g = (r, t, e) => t in r ? f(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var l = (r, t, e) => g(r, typeof t != "symbol" ? t + "" : t, e);
4
- const h = "application/x-postmate-v1+json";
5
- let y = 0;
6
- const P = {
1
+ const c = "application/x-postmate-v1+json";
2
+ let m = 0;
3
+ const f = {
7
4
  handshake: 1,
8
5
  "handshake-reply": 1,
9
6
  call: 1,
@@ -11,26 +8,26 @@ const P = {
11
8
  reply: 1,
12
9
  request: 1
13
10
  };
14
- function p(r, t) {
15
- return (typeof t != "string" || r.origin === t) && !!r.data && (typeof r.data != "object" || "postmate" in r.data) && r.data.type === h && !!P[r.data.postmate];
11
+ function p(n, t) {
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];
16
13
  }
17
- class w {
14
+ class g {
18
15
  constructor(t) {
19
16
  this.parent = t.parent, this.frame = t.frame, this.child = t.child, this.childOrigin = t.childOrigin, this.events = {}, this.listener = (e) => {
20
17
  if (!p(e, this.childOrigin)) return;
21
- const { value: s = {} } = e.data, { name: a, data: i } = s;
22
- e.data.postmate === "emit" && a in this.events && this.events[a].call(this, i);
18
+ const { value: s = {} } = e.data, { name: a, data: r } = s;
19
+ e.data.postmate === "emit" && a in this.events && this.events[a].call(this, r);
23
20
  }, this.parent.addEventListener("message", this.listener, !1);
24
21
  }
25
22
  get(t) {
26
23
  return new o.Promise((e) => {
27
- const s = ++y, a = (i) => {
28
- i.data.uid === s && i.data.postmate === "reply" && (this.parent.removeEventListener("message", a, !1), e(i.data.value));
24
+ const s = ++m, a = (r) => {
25
+ r.data.uid === s && r.data.postmate === "reply" && (this.parent.removeEventListener("message", a, !1), e(r.data.value));
29
26
  };
30
27
  this.parent.addEventListener("message", a, !1), this.child.postMessage(
31
28
  {
32
29
  postmate: "request",
33
- type: h,
30
+ type: c,
34
31
  property: t,
35
32
  uid: s
36
33
  },
@@ -42,7 +39,7 @@ class w {
42
39
  this.child.postMessage(
43
40
  {
44
41
  postmate: "call",
45
- type: h,
42
+ type: c,
46
43
  property: t,
47
44
  data: e
48
45
  },
@@ -56,33 +53,33 @@ class w {
56
53
  window.removeEventListener("message", this.listener, !1), this.frame.parentNode.removeChild(this.frame);
57
54
  }
58
55
  }
59
- class E {
56
+ class P {
60
57
  constructor(t) {
61
58
  this.model = t.model, this.parent = t.parent, this.parentOrigin = t.parentOrigin, this.child = t.child, this.child.addEventListener("message", (e) => {
62
59
  if (!p(e, this.parentOrigin)) return;
63
- const { postmate: s, property: a, uid: i, data: d } = e.data, n = this.model[a];
60
+ const { postmate: s, property: a, uid: r, data: h } = e.data, i = this.model[a];
64
61
  if (s !== "call") {
65
- const c = typeof n == "function" ? n() : n;
66
- o.Promise.resolve(c).then((m) => {
62
+ const l = typeof i == "function" ? i() : i;
63
+ o.Promise.resolve(l).then((d) => {
67
64
  e.source.postMessage(
68
65
  {
69
66
  property: a,
70
67
  postmate: "reply",
71
- type: h,
72
- uid: i,
73
- value: m
68
+ type: c,
69
+ uid: r,
70
+ value: d
74
71
  },
75
72
  e.origin
76
73
  );
77
74
  });
78
- } else a in this.model && typeof n == "function" && n(d);
75
+ } else a in this.model && typeof i == "function" && i(h);
79
76
  });
80
77
  }
81
78
  emit(t, e) {
82
79
  this.parent.postMessage(
83
80
  {
84
81
  postmate: "emit",
85
- type: h,
82
+ type: c,
86
83
  value: { name: t, data: e }
87
84
  },
88
85
  this.parentOrigin
@@ -90,40 +87,40 @@ class E {
90
87
  }
91
88
  }
92
89
  class o {
93
- constructor({ container: t = document.body, model: e, url: s, name: a, classListArray: i = [] }) {
94
- return this.parent = window, this.frame = document.createElement("iframe"), this.frame.name = a || "", this.frame.classList.add(...i), t.appendChild(this.frame), this.child = this.frame.contentWindow, this.model = e || {}, this.sendHandshake(s);
90
+ constructor({ container: t = document.body, model: e, url: s, name: a, classListArray: r = [] }) {
91
+ 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);
95
92
  }
96
93
  sendHandshake(t) {
97
94
  const e = (() => {
98
- const i = document.createElement("a");
99
- i.href = t;
100
- const d = i.protocol.length > 4 ? i.protocol : window.location.protocol, n = i.host.length ? i.port === "80" || i.port === "443" ? i.hostname : i.host : window.location.host;
101
- return i.origin || `${d}//${n}`;
95
+ const r = document.createElement("a");
96
+ r.href = t;
97
+ const h = 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;
98
+ return r.origin || `${h}//${i}`;
102
99
  })();
103
100
  let s = 0, a;
104
- return new o.Promise((i, d) => {
105
- const n = (u) => {
101
+ return new o.Promise((r, h) => {
102
+ const i = (u) => {
106
103
  if (!p(u, e)) return !1;
107
- u.data.postmate === "handshake-reply" ? (clearInterval(a), this.parent.removeEventListener("message", n, !1), this.childOrigin = u.origin, i(new w(this))) : d("Failed handshake");
104
+ u.data.postmate === "handshake-reply" ? (clearInterval(a), this.parent.removeEventListener("message", i, !1), this.childOrigin = u.origin, r(new g(this))) : h("Failed handshake");
108
105
  };
109
- this.parent.addEventListener("message", n, !1);
110
- const c = () => {
106
+ this.parent.addEventListener("message", i, !1);
107
+ const l = () => {
111
108
  s++, this.child.postMessage(
112
109
  {
113
110
  postmate: "handshake",
114
- type: h,
111
+ type: c,
115
112
  model: this.model
116
113
  },
117
114
  e
118
115
  ), s === 5 && clearInterval(a);
119
- }, m = () => {
120
- c(), a = setInterval(c, 500);
116
+ }, d = () => {
117
+ l(), a = setInterval(l, 500);
121
118
  };
122
- this.frame.onload = m, this.frame.attachEvent && this.frame.attachEvent("onload", m), this.frame.src = t;
119
+ this.frame.onload = d, this.frame.attachEvent && this.frame.attachEvent("onload", d), this.frame.src = t;
123
120
  });
124
121
  }
125
122
  }
126
- class I {
123
+ class y {
127
124
  constructor(t) {
128
125
  return this.child = window, this.model = t, this.parent = window.parent, this.sendHandshakeReply();
129
126
  }
@@ -135,14 +132,14 @@ class I {
135
132
  this.child.removeEventListener("message", this, !1), s.source.postMessage(
136
133
  {
137
134
  postmate: "handshake-reply",
138
- type: h
135
+ type: c
139
136
  },
140
137
  s.origin
141
138
  ), this.parentOrigin = s.origin;
142
139
  const a = s.data.model;
143
- a && Object.keys(a).forEach((i) => {
144
- this.model[i] = a[i];
145
- }), t(new E(this));
140
+ a && Object.keys(a).forEach((r) => {
141
+ this.model[r] = a[r];
142
+ }), t(new P(this));
146
143
  }
147
144
  }, !1);
148
145
  });
@@ -156,10 +153,10 @@ o.Promise = (() => {
156
153
  return Promise;
157
154
  }
158
155
  })();
159
- o.Model = I;
160
- class k {
161
- constructor(t) {
162
- this.childPostmate = null, this.parentPostmate = null, this.isGetData = !1, this.getDataCllBack = null, window.top !== window.self ? this.init(t) : t.error({ status: 500, data: null, message: "未在一体化平台中运行" });
156
+ o.Model = y;
157
+ class w {
158
+ constructor(t, e, s) {
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: "未在一体化平台中运行" });
163
160
  }
164
161
  init(t) {
165
162
  const e = this;
@@ -175,6 +172,19 @@ class k {
175
172
  message: "success",
176
173
  data: s
177
174
  }), e.isGetData = !1;
175
+ },
176
+ // 处理路由更新
177
+ routeUpdate(s) {
178
+ try {
179
+ const a = JSON.parse(s);
180
+ if (e.routeUpdateCallback) {
181
+ e.routeUpdateCallback(a);
182
+ return;
183
+ }
184
+ e.router ? e.router.replace(a.fullPath) : console.warn("未提供router实例,无法进行路由更新");
185
+ } catch (a) {
186
+ console.error("路由更新失败:", a);
187
+ }
178
188
  }
179
189
  }).then((s) => {
180
190
  e.parentPostmate = s, e.getData(), t.success({
@@ -200,25 +210,63 @@ class k {
200
210
  }
201
211
  t ? (this.isGetData = !0, this.getDataCllBack = t) : (this.isGetData = !1, this.getDataCllBack = null), this.parentPostmate.emit("requestBaseData");
202
212
  }
213
+ /**
214
+ * 设置路由实例和路由更新回调
215
+ * @param router Vue Router实例
216
+ * @param routeUpdateCallback 自定义路由更新回调函数
217
+ */
218
+ setRouter(t, e) {
219
+ this.router = t, e && (this.routeUpdateCallback = e);
220
+ }
221
+ /**
222
+ * 向父页面发送其他请求
223
+ * @param params 请求参数
224
+ */
225
+ sendOtherRequest(t) {
226
+ this.parentPostmate && this.parentPostmate.emit("otherRequest", t);
227
+ }
203
228
  }
204
- class v {
205
- constructor(t, e = null, s = "") {
206
- /** 连接到的子 postmate 实例 */
207
- l(this, "postmateParent", null);
208
- /** 通讯数据 */
209
- l(this, "dataInfo", {
210
- loginInfo: null,
229
+ class U {
230
+ constructor(t, e, s = "", a) {
231
+ this.postmateParent = null, this.dataInfo = {
232
+ loginInfo: {},
211
233
  token: "",
212
234
  isHideHeader: !0
213
- });
214
- /** iframe Dom 容器 */
215
- l(this, "iframeEle", null);
216
- /** 当前 iframe url */
217
- l(this, "currentUrl", "");
218
- /** 存储当前的 iframe 元素 */
219
- l(this, "currentIframe", null);
220
- l(this, "loadFunction", null);
221
- this.dataInfo = t || this.dataInfo, this.setIframeEle(e), this.setIframeUrl(s);
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);
236
+ }
237
+ /** 解析URL */
238
+ parseUrl(t) {
239
+ const e = document.createElement("a");
240
+ 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}` : ""}`, u = `${h}${i}${l}`;
242
+ return {
243
+ protocol: s,
244
+ host: a,
245
+ port: r,
246
+ pathname: h,
247
+ search: i,
248
+ hash: l,
249
+ origin: d,
250
+ fullPath: u
251
+ };
252
+ }
253
+ /** 比较两个URL是否相同(协议、主机、端口) */
254
+ compareUrlBase(t, e) {
255
+ if (!t || !e) return !1;
256
+ const s = this.parseUrl(t), a = this.parseUrl(e);
257
+ return s.protocol === a.protocol && s.host === a.host && s.port === a.port;
258
+ }
259
+ /** 比较两个URL的路径是否相同(不包含查询参数和哈希) */
260
+ compareUrlPath(t, e) {
261
+ if (!t || !e) return !1;
262
+ const s = this.parseUrl(t), a = this.parseUrl(e);
263
+ return s.pathname === a.pathname;
264
+ }
265
+ /** 比较两个URL是否完全相同(包括查询参数和哈希) */
266
+ compareUrlFull(t, e) {
267
+ if (!t || !e) return !1;
268
+ const s = this.parseUrl(t), a = this.parseUrl(e);
269
+ return s.fullPath === a.fullPath;
222
270
  }
223
271
  /** 清除当前的 iframe 和 postmate 实例 */
224
272
  clear() {
@@ -237,13 +285,17 @@ class v {
237
285
  }
238
286
  const s = new o({
239
287
  container: e,
240
- url: this.currentUrl
288
+ url: this.currentUrl,
289
+ name: "",
290
+ model: ""
241
291
  });
242
- this.currentIframe = e.querySelector("iframe"), this.currentIframe.addEventListener("load", () => {
243
- this.loadFunction();
292
+ this.currentIframe = e.querySelector("iframe"), this.currentIframe.setAttribute("frameborder", "0"), this.currentIframe.setAttribute("allow", "fullscreen"), this.currentIframe.addEventListener("load", () => {
293
+ this.loadFunction && this.loadFunction();
244
294
  }), s.then((a) => {
245
- console.log("parent", a), this.postmateParent = a, a.on("requestBaseData", (i) => {
295
+ this.postmateParent = a, a.on("requestBaseData", () => {
246
296
  this.sendData();
297
+ }), a.on("otherRequest", (r) => {
298
+ this.handleOtherRequest && this.handleOtherRequest(r);
247
299
  }), typeof t == "function" && t();
248
300
  }).catch((a) => {
249
301
  console.error("Postmate 连接失败:", a);
@@ -253,13 +305,37 @@ class v {
253
305
  setLoadFunction(t) {
254
306
  this.loadFunction = t;
255
307
  }
256
- /** 设置 iframe Dom */
257
- setIframeEle(t) {
258
- this.iframeEle !== t && (this.iframeEle = t, this.iframeEle && this.currentUrl && this.init());
259
- }
260
308
  /** 设置 iframe url */
261
309
  setIframeUrl(t) {
262
- this.currentUrl !== t && (this.currentUrl = t, this.iframeEle && this.currentUrl && this.init());
310
+ if (this.currentUrl === t) return;
311
+ if (!this.currentUrl) {
312
+ this.currentUrl = t, this.parsedCurrentUrl = this.parseUrl(t), this.iframeEle && this.init();
313
+ return;
314
+ }
315
+ const e = this.parseUrl(t);
316
+ if (this.postmateParent && this.compareUrlBase(this.currentUrl, t))
317
+ if (this.compareUrlPath(this.currentUrl, t)) {
318
+ if (this.compareUrlFull(this.currentUrl, t))
319
+ return;
320
+ this.currentUrl = t, this.parsedCurrentUrl = e, this.sendRouteUpdate(e);
321
+ return;
322
+ } else {
323
+ this.currentUrl = t, this.parsedCurrentUrl = e, this.sendRouteUpdate(e);
324
+ return;
325
+ }
326
+ this.currentUrl = t, this.parsedCurrentUrl = e, this.iframeEle && this.init();
327
+ }
328
+ /** 向子页面发送路由更新消息 */
329
+ sendRouteUpdate(t) {
330
+ this.postmateParent && this.postmateParent.call(
331
+ "routeUpdate",
332
+ JSON.stringify({
333
+ fullPath: t.fullPath,
334
+ pathname: t.pathname,
335
+ search: t.search,
336
+ hash: t.hash
337
+ })
338
+ );
263
339
  }
264
340
  /** 向子页面发送消息 */
265
341
  sendData() {
@@ -271,6 +347,6 @@ class v {
271
347
  }
272
348
  }
273
349
  export {
274
- k as ChildPostmate,
275
- v as ParentPostmate
350
+ w as ChildPostmate,
351
+ U as ParentPostmate
276
352
  };
Binary file
package/lib/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(n,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(n=typeof globalThis<"u"?globalThis:n||self,r(n["qlfy-postmate"]={}))})(this,function(n){"use strict";var k=Object.defineProperty;var v=(n,r,c)=>r in n?k(n,r,{enumerable:!0,configurable:!0,writable:!0,value:c}):n[r]=c;var d=(n,r,c)=>v(n,typeof r!="symbol"?r+"":r,c);const r="application/x-postmate-v1+json";let c=0;const y={handshake:1,"handshake-reply":1,call:1,emit:1,reply:1,request:1};function p(o,t){return(typeof t!="string"||o.origin===t)&&!!o.data&&(typeof o.data!="object"||"postmate"in o.data)&&o.data.type===r&&!!y[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(!p(e,this.childOrigin))return;const{value:s={}}=e.data,{name:a,data:i}=s;e.data.postmate==="emit"&&a in this.events&&this.events[a].call(this,i)},this.parent.addEventListener("message",this.listener,!1)}get(t){return new l.Promise(e=>{const s=++c,a=i=>{i.data.uid===s&&i.data.postmate==="reply"&&(this.parent.removeEventListener("message",a,!1),e(i.data.value))};this.parent.addEventListener("message",a,!1),this.child.postMessage({postmate:"request",type:r,property:t,uid:s},this.childOrigin)})}call(t,e){this.child.postMessage({postmate:"call",type:r,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(!p(e,this.parentOrigin))return;const{postmate:s,property:a,uid:i,data:m}=e.data,h=this.model[a];if(s!=="call"){const u=typeof h=="function"?h():h;l.Promise.resolve(u).then(f=>{e.source.postMessage({property:a,postmate:"reply",type:r,uid:i,value:f},e.origin)})}else a in this.model&&typeof h=="function"&&h(m)})}emit(t,e){this.parent.postMessage({postmate:"emit",type:r,value:{name:t,data:e}},this.parentOrigin)}}class l{constructor({container:t=document.body,model:e,url:s,name:a,classListArray:i=[]}){return this.parent=window,this.frame=document.createElement("iframe"),this.frame.name=a||"",this.frame.classList.add(...i),t.appendChild(this.frame),this.child=this.frame.contentWindow,this.model=e||{},this.sendHandshake(s)}sendHandshake(t){const e=(()=>{const i=document.createElement("a");i.href=t;const m=i.protocol.length>4?i.protocol:window.location.protocol,h=i.host.length?i.port==="80"||i.port==="443"?i.hostname:i.host:window.location.host;return i.origin||`${m}//${h}`})();let s=0,a;return new l.Promise((i,m)=>{const h=g=>{if(!p(g,e))return!1;g.data.postmate==="handshake-reply"?(clearInterval(a),this.parent.removeEventListener("message",h,!1),this.childOrigin=g.origin,i(new P(this))):m("Failed handshake")};this.parent.addEventListener("message",h,!1);const u=()=>{s++,this.child.postMessage({postmate:"handshake",type:r,model:this.model},e),s===5&&clearInterval(a)},f=()=>{u(),a=setInterval(u,500)};this.frame.onload=f,this.frame.attachEvent&&this.frame.attachEvent("onload",f),this.frame.src=t})}}class E{constructor(t){return this.child=window,this.model=t,this.parent=window.parent,this.sendHandshakeReply()}sendHandshakeReply(){return new l.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:r},s.origin),this.parentOrigin=s.origin;const a=s.data.model;a&&Object.keys(a).forEach(i=>{this.model[i]=a[i]}),t(new w(this))}},!1)})}}l.debug=!1,l.Promise=(()=>{try{return typeof window<"u"?window.Promise:Promise}catch{return Promise}})(),l.Model=E;class I{constructor(t){this.childPostmate=null,this.parentPostmate=null,this.isGetData=!1,this.getDataCllBack=null,window.top!==window.self?this.init(t):t.error({status:500,data:null,message:"未在一体化平台中运行"})}init(t){const e=this;this.childPostmate=new l.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}}).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")}}class D{constructor(t,e=null,s=""){d(this,"postmateParent",null);d(this,"dataInfo",{loginInfo:null,token:"",isHideHeader:!0});d(this,"iframeEle",null);d(this,"currentUrl","");d(this,"currentIframe",null);d(this,"loadFunction",null);this.dataInfo=t||this.dataInfo,this.setIframeEle(e),this.setIframeUrl(s)}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.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 l({container:e,url:this.currentUrl});this.currentIframe=e.querySelector("iframe"),this.currentIframe.addEventListener("load",()=>{this.loadFunction()}),s.then(a=>{console.log("parent",a),this.postmateParent=a,a.on("requestBaseData",i=>{this.sendData()}),typeof t=="function"&&t()}).catch(a=>{console.error("Postmate 连接失败:",a)})}setLoadFunction(t){this.loadFunction=t}setIframeEle(t){this.iframeEle!==t&&(this.iframeEle=t,this.iframeEle&&this.currentUrl&&this.init())}setIframeUrl(t){this.currentUrl!==t&&(this.currentUrl=t,this.iframeEle&&this.currentUrl&&this.init())}sendData(){this.postmateParent&&this.postmateParent.call("baseData",JSON.stringify(this.dataInfo))}destroy(){this.clear()}}n.ChildPostmate=I,n.ParentPostmate=D,Object.defineProperty(n,Symbol.toStringTag,{value:"Module"})});
1
+ (function(c,n){typeof exports=="object"&&typeof module<"u"?n(exports):typeof define=="function"&&define.amd?define(["exports"],n):(c=typeof globalThis<"u"?globalThis:c||self,n(c["qlfy-postmate"]={}))})(this,function(c){"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 y{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 d=typeof i=="function"?i():i;h.Promise.resolve(d).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 d=()=>{s++,this.child.postMessage({postmate:"handshake",type:n,model:this.model},e),s===5&&clearInterval(a)},u=()=>{d(),a=setInterval(d,500)};this.frame.onload=u,this.frame.attachEvent&&this.frame.attachEvent("onload",u),this.frame.src=t})}}class w{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 y(this))}},!1)})}}h.debug=!1,h.Promise=(()=>{try{return typeof window<"u"?window.Promise:Promise}catch{return Promise}})(),h.Model=w;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{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.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,d=e.hash,u=e.origin||`${s}//${a}${r?`:${r}`:""}`,p=`${l}${i}${d}`;return{protocol:s,host:a,port:r,pathname:l,search:i,hash:d,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.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))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){this.postmateParent&&this.postmateParent.call("routeUpdate",JSON.stringify({fullPath:t.fullPath,pathname:t.pathname,search:t.search,hash:t.hash}))}sendData(){this.postmateParent&&this.postmateParent.call("baseData",JSON.stringify(this.dataInfo))}destroy(){this.clear()}}c.ChildPostmate=U,c.ParentPostmate=E,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
@@ -3,13 +3,32 @@ interface EventObj {
3
3
  success: (success: any) => void;
4
4
  receive: (receive: any) => void;
5
5
  }
6
+ interface RouteUpdateInfo {
7
+ fullPath: string;
8
+ pathname: string;
9
+ search: string;
10
+ hash: string;
11
+ }
6
12
  export default class ChildPostmate {
7
13
  childPostmate: any;
8
14
  parentPostmate: any;
9
15
  isGetData: boolean;
10
16
  getDataCllBack: Function | null;
11
- constructor(eventObj: EventObj);
17
+ router: any;
18
+ routeUpdateCallback: ((routeInfo: RouteUpdateInfo) => void) | null;
19
+ constructor(eventObj: EventObj, router?: any, routeUpdateCallback?: (routeInfo: RouteUpdateInfo) => void);
12
20
  init(eventObj: EventObj): void;
13
21
  getData(callback?: any): void;
22
+ /**
23
+ * 设置路由实例和路由更新回调
24
+ * @param router Vue Router实例
25
+ * @param routeUpdateCallback 自定义路由更新回调函数
26
+ */
27
+ setRouter(router: any, routeUpdateCallback?: (routeInfo: RouteUpdateInfo) => void): void;
28
+ /**
29
+ * 向父页面发送其他请求
30
+ * @param params 请求参数
31
+ */
32
+ sendOtherRequest(params: any): void;
14
33
  }
15
34
  export {};
@@ -0,0 +1,59 @@
1
+ interface DataInfo {
2
+ loginInfo: {
3
+ [x: string]: any;
4
+ };
5
+ token: string;
6
+ isHideHeader: boolean;
7
+ }
8
+ interface ParsedUrl {
9
+ protocol: string;
10
+ host: string;
11
+ port: string;
12
+ pathname: string;
13
+ search: string;
14
+ hash: string;
15
+ origin: string;
16
+ fullPath: string;
17
+ }
18
+ export default class ParentPostmate {
19
+ /** 连接到的子 postmate 实例 */
20
+ postmateParent: any;
21
+ /** 通讯数据 */
22
+ dataInfo: DataInfo;
23
+ /** iframe Dom 容器 */
24
+ iframeEle: any;
25
+ /** 当前 iframe url */
26
+ currentUrl: string;
27
+ /** 存储当前的 iframe 元素 */
28
+ currentIframe: any;
29
+ /** iframe 加载完成执行函数 */
30
+ loadFunction: (() => void) | null;
31
+ /** 处理子类的其他请求方法 */
32
+ handleOtherRequest: ((params: any) => void) | null;
33
+ /** 当前URL解析结果 */
34
+ parsedCurrentUrl: ParsedUrl | null;
35
+ constructor(dataInfo: DataInfo, iframeEle: HTMLElement | (() => HTMLElement), iframeUrl?: string, handleOtherRequest?: (params: any) => void);
36
+ /** 解析URL */
37
+ parseUrl(url: string): ParsedUrl;
38
+ /** 比较两个URL是否相同(协议、主机、端口) */
39
+ compareUrlBase(url1: string, url2: string): boolean;
40
+ /** 比较两个URL的路径是否相同(不包含查询参数和哈希) */
41
+ compareUrlPath(url1: string, url2: string): boolean;
42
+ /** 比较两个URL是否完全相同(包括查询参数和哈希) */
43
+ compareUrlFull(url1: string, url2: string): boolean;
44
+ /** 清除当前的 iframe 和 postmate 实例 */
45
+ clear(): void;
46
+ /** 初始化 */
47
+ init(callback?: any): Promise<void>;
48
+ /** 设置load执行事件 */
49
+ setLoadFunction(loadFunction: any): void;
50
+ /** 设置 iframe url */
51
+ setIframeUrl(iframeUrl: string): void;
52
+ /** 向子页面发送路由更新消息 */
53
+ sendRouteUpdate(parsedUrl: ParsedUrl): void;
54
+ /** 向子页面发送消息 */
55
+ sendData(): void;
56
+ /** 销毁实例 */
57
+ destroy(): void;
58
+ }
59
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qlfy-postmate",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "",
5
5
  "types": "lib/index.d.ts",
6
6
  "module": "lib/index.umd.js",