@ibiz-template/vue3-util 0.0.4-beta.3 → 0.0.4-beta.5

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/dist/index.esm.js CHANGED
@@ -5,16 +5,18 @@ function useNamespace(block) {
5
5
  }
6
6
 
7
7
  // src/use/route/route.ts
8
- import { useRoute } from "vue-router";
9
- import { ref, watch as watch2 } from "vue";
8
+ import { useRoute as useRoute2 } from "vue-router";
9
+ import { ref, watch as watch3 } from "vue";
10
10
 
11
11
  // src/util/route/route.ts
12
12
  import { notNilEmpty } from "qx-util";
13
13
  import { RuntimeError } from "@ibiz-template/core";
14
14
  import qs from "qs";
15
+ import { useRoute } from "vue-router";
16
+ import { watch } from "vue";
15
17
  function getOwnRouteContext(context) {
16
18
  const ownContext = context.getOwnContext();
17
- const excludeKeys = ["srfsessionid"];
19
+ const excludeKeys = ["srfsessionid", "srfappid"];
18
20
  Object.keys(ownContext).forEach((key) => {
19
21
  if (excludeKeys.includes(key)) {
20
22
  delete ownContext[key];
@@ -24,12 +26,12 @@ function getOwnRouteContext(context) {
24
26
  }
25
27
  function generateRoutePath(appView, route, context, params) {
26
28
  const routePath = route2routePath(route);
27
- let level = 2;
28
- if (context.toRouteLevel) {
29
- level = context.toRouteLevel;
30
- delete context.toRouteLevel;
29
+ let depth = 2;
30
+ if (context.toRouteDepth) {
31
+ depth = context.toRouteDepth;
32
+ delete context.toRouteDepth;
31
33
  }
32
- routePath.pathNodes.splice(level - 1, routePath.pathNodes.length - level + 1);
34
+ routePath.pathNodes.splice(depth - 1, routePath.pathNodes.length - depth + 1);
33
35
  if (context.currentSrfNav) {
34
36
  const currentNode = routePath.pathNodes[routePath.pathNodes.length - 1];
35
37
  currentNode.params = currentNode.params || {};
@@ -51,21 +53,12 @@ function generateRoutePath(appView, route, context, params) {
51
53
  });
52
54
  return { path: routePath2string(routePath) };
53
55
  }
54
- function getViewName(model) {
55
- return model.codeName.toLowerCase();
56
- }
57
- function findViewByName(_appModel, _viewCodeName) {
58
- return void 0;
59
- }
60
- function findView(_appModel, _viewCodeName) {
61
- return void 0;
62
- }
63
- async function parseRouteViewData(route, level) {
56
+ async function parseRouteViewData(route, depth) {
64
57
  var _a;
65
58
  const routePath = route2routePath(route);
66
- let viewCodeName = routePath.pathNodes[level - 1].viewName;
59
+ let viewCodeName = routePath.pathNodes[depth - 1].viewName;
67
60
  if (!viewCodeName) {
68
- throw new RuntimeError(`\u7B2C${level}\u7EA7\u8DEF\u7531\u4E0D\u5B58\u5728\u89C6\u56FE\u6807\u8BC6`);
61
+ throw new RuntimeError(`\u7B2C${depth}\u7EA7\u8DEF\u7531\u4E0D\u5B58\u5728\u89C6\u56FE\u6807\u8BC6`);
69
62
  }
70
63
  if (viewCodeName === "index") {
71
64
  viewCodeName = ibiz.hub.defaultAppIndexViewName;
@@ -81,13 +74,13 @@ async function parseRouteViewData(route, level) {
81
74
  if (routePath.appContext) {
82
75
  Object.assign(context, routePath.appContext);
83
76
  }
84
- for (let index = 0; index < level; index++) {
77
+ for (let index = 0; index < depth; index++) {
85
78
  const pathNode = routePath.pathNodes[index];
86
79
  if (notNilEmpty(pathNode.context)) {
87
80
  Object.assign(context, pathNode.context);
88
81
  }
89
82
  }
90
- const { params, srfnav } = routePath.pathNodes[level - 1];
83
+ const { params, srfnav } = routePath.pathNodes[depth - 1];
91
84
  return {
92
85
  viewModel,
93
86
  context,
@@ -96,9 +89,9 @@ async function parseRouteViewData(route, level) {
96
89
  };
97
90
  }
98
91
  function route2routePath(route) {
99
- const level = route.matched.length;
92
+ const depth = route.matched.length;
100
93
  const pathNodes = [];
101
- for (let index = 1; index <= level; index++) {
94
+ for (let index = 1; index <= depth; index++) {
102
95
  const viewName = route.params[`view${index}`];
103
96
  const paramsStr = route.params[`params${index}`];
104
97
  let params;
@@ -168,9 +161,26 @@ function routePath2string(routePath) {
168
161
  });
169
162
  return pathStr;
170
163
  }
164
+ function onRouteChange(callback, depth) {
165
+ const route = useRoute();
166
+ watch(
167
+ () => route.path,
168
+ () => {
169
+ const routePath = route2routePath(route);
170
+ let currentKey = "";
171
+ if (routePath.pathNodes.length >= depth) {
172
+ routePath.pathNodes = routePath.pathNodes.slice(0, depth);
173
+ delete routePath.pathNodes[depth - 1].srfnav;
174
+ currentKey = routePath2string(routePath);
175
+ }
176
+ callback({ currentKey, fullPath: route.fullPath });
177
+ },
178
+ { immediate: true }
179
+ );
180
+ }
171
181
 
172
182
  // src/util/route/route-listener.ts
173
- import { watch } from "vue";
183
+ import { watch as watch2 } from "vue";
174
184
  var RouteListener = class {
175
185
  constructor(route, wait) {
176
186
  /**
@@ -198,7 +208,7 @@ var RouteListener = class {
198
208
  if (wait) {
199
209
  this.wait = wait;
200
210
  }
201
- watch(
211
+ watch2(
202
212
  () => route.path,
203
213
  (newVal, oldVal) => {
204
214
  if (newVal !== oldVal) {
@@ -240,9 +250,17 @@ var RouteListener = class {
240
250
  }
241
251
  };
242
252
 
253
+ // src/util/install.ts
254
+ var withInstall = (main, install) => {
255
+ main.install = (app) => {
256
+ install(app);
257
+ };
258
+ return main;
259
+ };
260
+
243
261
  // src/use/route/route.ts
244
262
  function useRouterQuery() {
245
- const route = useRoute();
263
+ const route = useRoute2();
246
264
  const { query } = route;
247
265
  return query;
248
266
  }
@@ -252,7 +270,7 @@ function useRouteKey(originKey, route, routeKey) {
252
270
  }
253
271
  routeKey.value = originKey.value;
254
272
  const routeListener = new RouteListener(route);
255
- watch2(originKey, (newVal, oldVal) => {
273
+ watch3(originKey, (newVal, oldVal) => {
256
274
  if (newVal !== oldVal) {
257
275
  routeListener.nextChange(() => {
258
276
  routeKey.value = newVal;
@@ -269,7 +287,7 @@ import {
269
287
  getCurrentInstance,
270
288
  isReactive,
271
289
  toRaw,
272
- watch as watch3
290
+ watch as watch4
273
291
  } from "vue";
274
292
  function useProps() {
275
293
  const vue = getCurrentInstance().proxy;
@@ -281,7 +299,7 @@ function getOrigin(val) {
281
299
  function usePropsWatch(key, callback, options) {
282
300
  const props = useProps();
283
301
  if (Object.prototype.hasOwnProperty.call(props, key)) {
284
- watch3(
302
+ watch4(
285
303
  () => props[key],
286
304
  (newVal, oldVal) => {
287
305
  callback(getOrigin(newVal), getOrigin(oldVal));
@@ -327,7 +345,7 @@ import {
327
345
  onClickOutside
328
346
  } from "@ibiz-template/core";
329
347
  import { isNil } from "ramda";
330
- import { onBeforeUnmount, watch as watch4 } from "vue";
348
+ import { onBeforeUnmount, watch as watch5 } from "vue";
331
349
  function useClickOutside(elRef, handler, options = {}) {
332
350
  let stop = NOOP;
333
351
  let pause = NOOP;
@@ -338,7 +356,7 @@ function useClickOutside(elRef, handler, options = {}) {
338
356
  pause = NOOP;
339
357
  proceed = NOOP;
340
358
  };
341
- watch4(
359
+ watch5(
342
360
  elRef,
343
361
  (newVal, oldVal) => {
344
362
  if (newVal !== oldVal) {
@@ -373,10 +391,10 @@ function useClickOutside(elRef, handler, options = {}) {
373
391
  // src/use/event/event.ts
374
392
  import { listenJSEvent, NOOP as NOOP2 } from "@ibiz-template/core";
375
393
  import { isNil as isNil2 } from "ramda";
376
- import { onBeforeUnmount as onBeforeUnmount2, watch as watch5 } from "vue";
394
+ import { onBeforeUnmount as onBeforeUnmount2, watch as watch6 } from "vue";
377
395
  function useEventListener(elRef, eventName, listener, options = {}) {
378
396
  let cleanup = NOOP2;
379
- watch5(
397
+ watch6(
380
398
  elRef,
381
399
  (newVal, oldVal) => {
382
400
  if (newVal !== oldVal) {
@@ -406,7 +424,13 @@ function useEventListener(elRef, eventName, listener, options = {}) {
406
424
  }
407
425
 
408
426
  // src/use/view/use-view-controller/use-view-controller.ts
409
- import { inject, onBeforeUnmount as onBeforeUnmount3, provide, reactive } from "vue";
427
+ import {
428
+ getCurrentInstance as getCurrentInstance2,
429
+ inject,
430
+ onBeforeUnmount as onBeforeUnmount3,
431
+ provide,
432
+ reactive
433
+ } from "vue";
410
434
  function useViewController(fn) {
411
435
  const props = useProps();
412
436
  const ctx = inject("ctx", void 0);
@@ -417,14 +441,18 @@ function useViewController(fn) {
417
441
  if (props.modal) {
418
442
  c.modal = props.modal;
419
443
  }
444
+ const vue = getCurrentInstance2().proxy;
420
445
  c.force = useForce();
446
+ c.evt.onAll((eventName, event) => {
447
+ vue.$emit(eventName.slice(2), event);
448
+ });
421
449
  c.created();
422
450
  onBeforeUnmount3(() => c.destroyed());
423
451
  return c;
424
452
  }
425
453
 
426
454
  // src/use/widgets/use-control-controller/use-control-controller.ts
427
- import { inject as inject2, onBeforeUnmount as onBeforeUnmount4, reactive as reactive2 } from "vue";
455
+ import { getCurrentInstance as getCurrentInstance3, inject as inject2, onBeforeUnmount as onBeforeUnmount4, reactive as reactive2 } from "vue";
428
456
  function useControlController(fn) {
429
457
  const ctx = inject2("ctx");
430
458
  const props = useProps();
@@ -432,6 +460,10 @@ function useControlController(fn) {
432
460
  const c = fn(props.modelData, props.context, props.params, ctx);
433
461
  c.state = reactive2(c.state);
434
462
  c.force = useForce();
463
+ const vue = getCurrentInstance3().proxy;
464
+ c.evt.onAll((eventName, event) => {
465
+ vue.$emit(eventName, event);
466
+ });
435
467
  c.created();
436
468
  onBeforeUnmount4(() => c.destroyed());
437
469
  return c;
@@ -517,8 +549,6 @@ export {
517
549
  EmptyVNode,
518
550
  RequiredProp,
519
551
  RouteListener,
520
- findView,
521
- findViewByName,
522
552
  generateRoutePath,
523
553
  getEditorEmits,
524
554
  getEditorProps,
@@ -532,8 +562,8 @@ export {
532
562
  getInputProps,
533
563
  getOrigin,
534
564
  getOwnRouteContext,
535
- getViewName,
536
565
  isEmptyVNode,
566
+ onRouteChange,
537
567
  parseRouteViewData,
538
568
  route2routePath,
539
569
  routePath2string,
@@ -548,5 +578,6 @@ export {
548
578
  usePropsWatch,
549
579
  useRouteKey,
550
580
  useRouterQuery,
551
- useViewController
581
+ useViewController,
582
+ withInstall
552
583
  };
@@ -1 +1 @@
1
- System.register(["@ibiz-template/core","vue-router","vue","qx-util","qs","ramda"],(function(e){"use strict";var t,n,r,o,a,i,s,c,u,l,p,d,f,m,h,v,g,x,N,w;return{setters:[function(e){t=e.Namespace,n=e.RuntimeError,r=e.onClickOutside,o=e.NOOP,a=e.listenJSEvent},function(e){i=e.useRoute},function(e){s=e.createCommentVNode,c=e.watch,u=e.ref,l=e.getCurrentInstance,p=e.isReactive,d=e.toRaw,f=e.onBeforeUnmount,m=e.inject,h=e.provide,v=e.reactive},function(e){g=e.notNilEmpty,x=e.isFunc},function(e){N=e.default},function(e){w=e.isNil}],execute:function(){function b(e){const t=e.getOwnContext(),n=["srfsessionid"];return Object.keys(t).forEach((e=>{n.includes(e)&&delete t[e]})),t}function y(e){const t=e.matched.length,n=[];for(let r=1;r<=t;r++){const t=e.params[`view${r}`],o=e.params[`params${r}`];let a,i,s;a=o&&o!==ibiz.env.routePlaceholder?N.parse(o,{strictNullHandling:!0,delimiter:";"}):void 0,a&&(1===r?(i=a,a=void 0):(a.srfnavctx&&(i=JSON.parse(decodeURIComponent(a.srfnavctx)),delete a.srfnavctx),a.srfnav&&(s=a.srfnav,delete a.srfnav))),n.push({viewName:t,context:i,params:a,srfnav:s})}let r;return e.params.appContext&&e.params.appContext!==ibiz.env.routePlaceholder&&(r=N.parse(e.params.appContext,{strictNullHandling:!0,delimiter:";"})),{appContext:r,pathNodes:n}}function C(e){let t="";return e.appContext?t+=`/${N.stringify(e.appContext,{delimiter:";",strictNullHandling:!0})}`:t+=`/${ibiz.env.routePlaceholder}`,e.pathNodes.forEach(((e,n)=>{let r;if(t+=`/${e.viewName}/`,0===n)g(e.context)&&(r=e.context);else if(r=g(e.params)?e.params:{},g(e.context)){const t=JSON.stringify(e.context);"{}"!==t&&(r.srfnavctx=encodeURIComponent(t))}t+=N.stringify(r,{delimiter:";",strictNullHandling:!0})||ibiz.env.routePlaceholder})),t}e({findView:function(e,t){return},findViewByName:function(e,t){return},generateRoutePath:function(e,t,n,r){const o=y(t);let a=2;n.toRouteLevel&&(a=n.toRouteLevel,delete n.toRouteLevel);if(o.pathNodes.splice(a-1,o.pathNodes.length-a+1),n.currentSrfNav){const e=o.pathNodes[o.pathNodes.length-1];e.params=e.params||{},e.params.srfnav=n.currentSrfNav,delete n.currentSrfNav}t.fullPath.startsWith("/appredirectview")&&((null==r?void 0:r.srfindexname)?(o.pathNodes[0].viewName=r.srfindexname,delete r.srfindexname):o.pathNodes[0].viewName="index");return o.pathNodes.push({viewName:e.codeName.toLowerCase(),context:b(n),params:r}),{path:C(o)}},getEditorEmits:function(){return{change:(e,t)=>!0,operate:e=>!0}},getEditorProps:$,getGridEditorCommonProps:S,getGridEditorEmits:function(){return{change:(e,t)=>!0,rowSave:()=>!0}},getGridInputIpProps:function(){return{...j(),...S()}},getGridInputNumberProps:function(){return{...z(),...S()}},getGridInputProps:function(){return{...V(),...S()}},getInputIpProps:j,getInputNumberProps:z,getInputProps:V,getOrigin:E,getOwnRouteContext:b,getViewName:function(e){return e.codeName.toLowerCase()},isEmptyVNode:function(e){if(!Array.isArray(e))return e===I;return 1===e.length&&e[0]===I},parseRouteViewData:async function(e,t){var r;const o=y(e);let a=o.pathNodes[t-1].viewName;if(!a)throw new n(`第${t}级路由不存在视图标识`);"index"===a&&(a=ibiz.hub.defaultAppIndexViewName);const i=await ibiz.hub.getAppView(a);if(!i)throw new n(`找不到视图${a}`);const s={};(null==(r=ibiz.appData)?void 0:r.context)&&Object.assign(s,ibiz.appData.context);o.appContext&&Object.assign(s,o.appContext);for(let e=0;e<t;e++){const t=o.pathNodes[e];g(t.context)&&Object.assign(s,t.context)}const{params:c,srfnav:u}=o.pathNodes[t-1];return{viewModel:i,context:s,params:c,srfnav:u}},route2routePath:y,routePath2string:C,useClickOutside:function(e,t,n={}){let a=o,i=o,s=o;const u=()=>{a(),a=o,i=o,s=o};return c(e,((e,o)=>{if(e!==o)if(w(e))u();else{const o=r((null==e?void 0:e.$el)||e,t,n);a=o.stop,i=o.pause,s=o.proceed}}),{immediate:!0}),f((()=>{a!==o&&u()})),{stop:()=>a(),pause:()=>i(),proceed:()=>s()}},useControlController:function(e){const t=m("ctx"),n=O();t.evt.emit("forecast",n.modelData.name);const r=e(n.modelData,n.context,n.params,t);return r.state=v(r.state),r.force=R(),r.created(),f((()=>r.destroyed())),r},useController:function(e){e.force=R()},useEventListener:function(e,t,n,r={}){let i=o;return c(e,((e,s)=>{e!==s&&(w(e)?(i(),i=o):i=a((null==e?void 0:e.$el)||e,t,n,r))}),{immediate:!0}),f((()=>{i!==o&&i()})),()=>{i()}},useForce:R,useForceTogether:function(e,t){const n=t.force,r=R();t.force=e=>{n(e),r()}},useNamespace:function(e){return new t(e,ibiz.env.namespace)},useProps:O,usePropsWatch:function(e,t,n){const r=O();Object.prototype.hasOwnProperty.call(r,e)&&(c((()=>r[e]),((e,n)=>{t(E(e),E(n))}),n),t(E(r[e]),void 0))},useRouteKey:function(e,t,n){n||(n=u(""));n.value=e.value;const r=new P(t);return c(e,((e,t)=>{e!==t&&r.nextChange((()=>{n.value=e}))})),n},useRouterQuery:function(){const e=i(),{query:t}=e;return t},useViewController:function(e){const t=O(),n=m("ctx",void 0);null==n||n.evt.emit("forecast",t.modelData.name);const r=e(t.modelData,t.context,t.params,n);h("ctx",r.ctx),r.state=v(r.state),t.modal&&(r.modal=t.modal);return r.force=R(),r.created(),f((()=>r.destroyed())),r}});var P=e("RouteListener",class{constructor(e,t){this.callbacks=[],this.timers=[],this.wait=500,t&&(this.wait=t),c((()=>e.path),((e,t)=>{if(e!==t){if(this.callbacks.length)for(let e=0;e<this.callbacks.length;e++){(0,this.callbacks[e])()}if(this.callbacks=[],this.timers.length)for(let e=0;e<this.timers.length;e++){const t=this.timers[e];clearTimeout(t)}this.timers=[]}}))}nextChange(e){e&&(this.timers.push(setTimeout((()=>{e();const t=this.callbacks.findIndex((t=>t===e));this.callbacks.splice(t,1)}),this.wait)),this.callbacks.push(e))}});function O(){return l().proxy.$props}function E(e){return p(e)?d(e):e}function R(){const e=l().proxy;return t=>{e.$forceUpdate(),t&&x(t)&&e.$nextTick((()=>{t()}))}}var I=e("EmptyVNode",s("EmptyVNode"));var k=e("RequiredProp",class{constructor(e,t,n){this.required=!0,t&&(this.default=t),n&&(this.validator=n),this.type=e}});function $(){return{value:String,controller:new k(Object),data:new k(Object),disabled:{type:Boolean},readonly:{type:Boolean,default:!1},autoFocus:{type:Boolean,default:!1}}}function S(){return{hasError:{type:Boolean}}}function V(){return{...$(),value:String}}function z(){return{...$(),value:Number}}function j(){return{...$(),value:String}}}}}));
1
+ System.register(["@ibiz-template/core","vue-router","vue","qx-util","qs","ramda"],(function(t){"use strict";var e,n,o,r,a,s,i,c,u,l,p,d,f,h,m,v,g,x,N,w;return{setters:[function(t){e=t.Namespace,n=t.RuntimeError,o=t.onClickOutside,r=t.NOOP,a=t.listenJSEvent},function(t){s=t.useRoute},function(t){i=t.createCommentVNode,c=t.watch,u=t.ref,l=t.getCurrentInstance,p=t.isReactive,d=t.toRaw,f=t.onBeforeUnmount,h=t.inject,m=t.provide,v=t.reactive},function(t){g=t.notNilEmpty,x=t.isFunc},function(t){N=t.default},function(t){w=t.isNil}],execute:function(){function b(t){const e=t.getOwnContext(),n=["srfsessionid","srfappid"];return Object.keys(e).forEach((t=>{n.includes(t)&&delete e[t]})),e}function y(t){const e=t.matched.length,n=[];for(let o=1;o<=e;o++){const e=t.params[`view${o}`],r=t.params[`params${o}`];let a,s,i;a=r&&r!==ibiz.env.routePlaceholder?N.parse(r,{strictNullHandling:!0,delimiter:";"}):void 0,a&&(1===o?(s=a,a=void 0):(a.srfnavctx&&(s=JSON.parse(decodeURIComponent(a.srfnavctx)),delete a.srfnavctx),a.srfnav&&(i=a.srfnav,delete a.srfnav))),n.push({viewName:e,context:s,params:a,srfnav:i})}let o;return t.params.appContext&&t.params.appContext!==ibiz.env.routePlaceholder&&(o=N.parse(t.params.appContext,{strictNullHandling:!0,delimiter:";"})),{appContext:o,pathNodes:n}}function C(t){let e="";return t.appContext?e+=`/${N.stringify(t.appContext,{delimiter:";",strictNullHandling:!0})}`:e+=`/${ibiz.env.routePlaceholder}`,t.pathNodes.forEach(((t,n)=>{let o;if(e+=`/${t.viewName}/`,0===n)g(t.context)&&(o=t.context);else if(o=g(t.params)?t.params:{},g(t.context)){const e=JSON.stringify(t.context);"{}"!==e&&(o.srfnavctx=encodeURIComponent(e))}e+=N.stringify(o,{delimiter:";",strictNullHandling:!0})||ibiz.env.routePlaceholder})),e}t({generateRoutePath:function(t,e,n,o){const r=y(e);let a=2;n.toRouteDepth&&(a=n.toRouteDepth,delete n.toRouteDepth);if(r.pathNodes.splice(a-1,r.pathNodes.length-a+1),n.currentSrfNav){const t=r.pathNodes[r.pathNodes.length-1];t.params=t.params||{},t.params.srfnav=n.currentSrfNav,delete n.currentSrfNav}e.fullPath.startsWith("/appredirectview")&&((null==o?void 0:o.srfindexname)?(r.pathNodes[0].viewName=o.srfindexname,delete o.srfindexname):r.pathNodes[0].viewName="index");return r.pathNodes.push({viewName:t.codeName.toLowerCase(),context:b(n),params:o}),{path:C(r)}},getEditorEmits:function(){return{change:(t,e)=>!0,operate:t=>!0}},getEditorProps:k,getGridEditorCommonProps:S,getGridEditorEmits:function(){return{change:(t,e)=>!0,rowSave:()=>!0}},getGridInputIpProps:function(){return{...j(),...S()}},getGridInputNumberProps:function(){return{...D(),...S()}},getGridInputProps:function(){return{...z(),...S()}},getInputIpProps:j,getInputNumberProps:D,getInputProps:z,getOrigin:R,getOwnRouteContext:b,isEmptyVNode:function(t){if(!Array.isArray(t))return t===I;return 1===t.length&&t[0]===I},onRouteChange:function(t,e){const n=s();c((()=>n.path),(()=>{const o=y(n);let r="";o.pathNodes.length>=e&&(o.pathNodes=o.pathNodes.slice(0,e),delete o.pathNodes[e-1].srfnav,r=C(o)),t({currentKey:r,fullPath:n.fullPath})}),{immediate:!0})},parseRouteViewData:async function(t,e){var o;const r=y(t);let a=r.pathNodes[e-1].viewName;if(!a)throw new n(`第${e}级路由不存在视图标识`);"index"===a&&(a=ibiz.hub.defaultAppIndexViewName);const s=await ibiz.hub.getAppView(a);if(!s)throw new n(`找不到视图${a}`);const i={};(null==(o=ibiz.appData)?void 0:o.context)&&Object.assign(i,ibiz.appData.context);r.appContext&&Object.assign(i,r.appContext);for(let t=0;t<e;t++){const e=r.pathNodes[t];g(e.context)&&Object.assign(i,e.context)}const{params:c,srfnav:u}=r.pathNodes[e-1];return{viewModel:s,context:i,params:c,srfnav:u}},route2routePath:y,routePath2string:C,useClickOutside:function(t,e,n={}){let a=r,s=r,i=r;const u=()=>{a(),a=r,s=r,i=r};return c(t,((t,r)=>{if(t!==r)if(w(t))u();else{const r=o((null==t?void 0:t.$el)||t,e,n);a=r.stop,s=r.pause,i=r.proceed}}),{immediate:!0}),f((()=>{a!==r&&u()})),{stop:()=>a(),pause:()=>s(),proceed:()=>i()}},useControlController:function(t){const e=h("ctx"),n=O();e.evt.emit("forecast",n.modelData.name);const o=t(n.modelData,n.context,n.params,e);o.state=v(o.state),o.force=E();const r=l().proxy;return o.evt.onAll(((t,e)=>{r.$emit(t,e)})),o.created(),f((()=>o.destroyed())),o},useController:function(t){t.force=E()},useEventListener:function(t,e,n,o={}){let s=r;return c(t,((t,i)=>{t!==i&&(w(t)?(s(),s=r):s=a((null==t?void 0:t.$el)||t,e,n,o))}),{immediate:!0}),f((()=>{s!==r&&s()})),()=>{s()}},useForce:E,useForceTogether:function(t,e){const n=e.force,o=E();e.force=t=>{n(t),o()}},useNamespace:function(t){return new e(t,ibiz.env.namespace)},useProps:O,usePropsWatch:function(t,e,n){const o=O();Object.prototype.hasOwnProperty.call(o,t)&&(c((()=>o[t]),((t,n)=>{e(R(t),R(n))}),n),e(R(o[t]),void 0))},useRouteKey:function(t,e,n){n||(n=u(""));n.value=t.value;const o=new P(e);return c(t,((t,e)=>{t!==e&&o.nextChange((()=>{n.value=t}))})),n},useRouterQuery:function(){const t=s(),{query:e}=t;return e},useViewController:function(t){const e=O(),n=h("ctx",void 0);null==n||n.evt.emit("forecast",e.modelData.name);const o=t(e.modelData,e.context,e.params,n);m("ctx",o.ctx),o.state=v(o.state),e.modal&&(o.modal=e.modal);const r=l().proxy;return o.force=E(),o.evt.onAll(((t,e)=>{r.$emit(t.slice(2),e)})),o.created(),f((()=>o.destroyed())),o}});var P=t("RouteListener",class{constructor(t,e){this.callbacks=[],this.timers=[],this.wait=500,e&&(this.wait=e),c((()=>t.path),((t,e)=>{if(t!==e){if(this.callbacks.length)for(let t=0;t<this.callbacks.length;t++){(0,this.callbacks[t])()}if(this.callbacks=[],this.timers.length)for(let t=0;t<this.timers.length;t++){const e=this.timers[t];clearTimeout(e)}this.timers=[]}}))}nextChange(t){t&&(this.timers.push(setTimeout((()=>{t();const e=this.callbacks.findIndex((e=>e===t));this.callbacks.splice(e,1)}),this.wait)),this.callbacks.push(t))}});t("withInstall",((t,e)=>(t.install=t=>{e(t)},t)));function O(){return l().proxy.$props}function R(t){return p(t)?d(t):t}function E(){const t=l().proxy;return e=>{t.$forceUpdate(),e&&x(e)&&t.$nextTick((()=>{e()}))}}var I=t("EmptyVNode",i("EmptyVNode"));var $=t("RequiredProp",class{constructor(t,e,n){this.required=!0,e&&(this.default=e),n&&(this.validator=n),this.type=t}});function k(){return{value:String,controller:new $(Object),data:new $(Object),disabled:{type:Boolean},readonly:{type:Boolean,default:!1},autoFocus:{type:Boolean,default:!1}}}function S(){return{hasError:{type:Boolean}}}function z(){return{...k(),value:String}}function D(){return{...k(),value:Number}}function j(){return{...k(),value:String}}}}}));
@@ -1 +1 @@
1
- {"version":3,"file":"use-view-controller.d.ts","sourceRoot":"","sources":["../../../../src/use/view/use-view-controller/use-view-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,EACxD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,GAC/D,CAAC,CAyBH"}
1
+ {"version":3,"file":"use-view-controller.d.ts","sourceRoot":"","sources":["../../../../src/use/view/use-view-controller/use-view-controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAO,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAU7D;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,EACxD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,cAAc,CAAC,KAAK,CAAC,GAC/D,CAAC,CA8BH"}
@@ -1,4 +1,4 @@
1
- import { inject, onBeforeUnmount, provide, reactive } from 'vue';
1
+ import { getCurrentInstance, inject, onBeforeUnmount, provide, reactive, } from 'vue';
2
2
  import { useForce, useProps } from '../../vue/vue';
3
3
  /**
4
4
  * 初始化视图控制器
@@ -20,15 +20,18 @@ export function useViewController(fn) {
20
20
  ctx === null || ctx === void 0 ? void 0 : ctx.evt.emit('forecast', props.modelData.name);
21
21
  const c = fn(props.modelData, props.context, props.params, ctx);
22
22
  // 提供自身的ctx给下层组件
23
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
23
  provide('ctx', c.ctx);
25
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ // 让state 响应式
26
25
  c.state = reactive(c.state);
27
26
  // 从props赋值modal,如果存在的话。
28
27
  if (props.modal) {
29
28
  c.modal = props.modal;
30
29
  }
30
+ const vue = getCurrentInstance().proxy;
31
31
  c.force = useForce();
32
+ c.evt.onAll((eventName, event) => {
33
+ vue.$emit(eventName.slice(2), event);
34
+ });
32
35
  c.created();
33
36
  // 卸载时销毁
34
37
  onBeforeUnmount(() => c.destroyed());
@@ -1 +1 @@
1
- {"version":3,"file":"use-control-controller.d.ts","sourceRoot":"","sources":["../../../../src/use/widgets/use-control-controller/use-control-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAO,MAAM,wBAAwB,CAAC;AAIhE;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,iBAAiB,EAC9D,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,KAAK,CAAC,GAClE,CAAC,CAkBH"}
1
+ {"version":3,"file":"use-control-controller.d.ts","sourceRoot":"","sources":["../../../../src/use/widgets/use-control-controller/use-control-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAO,MAAM,wBAAwB,CAAC;AAIhE;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,iBAAiB,EAC9D,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,qBAAqB,CAAC,OAAO,iBAAiB,CAAC,KAAK,CAAC,GAClE,CAAC,CAwBH"}
@@ -1,4 +1,4 @@
1
- import { inject, onBeforeUnmount, reactive } from 'vue';
1
+ import { getCurrentInstance, inject, onBeforeUnmount, reactive } from 'vue';
2
2
  import { useForce, useProps } from '../../vue/vue';
3
3
  /**
4
4
  * 初始化部件控制器
@@ -20,6 +20,10 @@ export function useControlController(fn) {
20
20
  const c = fn(props.modelData, props.context, props.params, ctx);
21
21
  c.state = reactive(c.state);
22
22
  c.force = useForce();
23
+ const vue = getCurrentInstance().proxy;
24
+ c.evt.onAll((eventName, event) => {
25
+ vue.$emit(eventName, event);
26
+ });
23
27
  c.created();
24
28
  // 挂载强制更新方法
25
29
  // 卸载时销毁
@@ -1,3 +1,4 @@
1
1
  export * from './route/route';
2
2
  export * from './route/route-listener';
3
+ export * from './install';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/util/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,wBAAwB,CAAC;AACvC,cAAc,WAAW,CAAC"}
package/out/util/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './route/route';
2
2
  export * from './route/route-listener';
3
+ export * from './install';
@@ -0,0 +1,4 @@
1
+ import type { App, Plugin } from 'vue';
2
+ export type TypeWithInstall<T> = T & Plugin;
3
+ export declare const withInstall: <T>(main: T, install: (_v: App) => void) => TypeWithInstall<T>;
4
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/util/install.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAEvC,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;AAE5C,eAAO,MAAM,WAAW,6BAA8B,GAAG,KAAK,IAAI,uBAKjE,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const withInstall = (main, install) => {
2
+ main.install = (app) => {
3
+ install(app);
4
+ };
5
+ return main;
6
+ };
@@ -1,4 +1,4 @@
1
- import { IApplication, IAppView } from '@ibiz/model-core';
1
+ import { IAppView } from '@ibiz/model-core';
2
2
  import { RouteLocationNormalizedLoaded as Route } from 'vue-router';
3
3
  import { IRoutePath, IRouteViewData } from '../../interface';
4
4
  /**
@@ -26,32 +26,6 @@ export declare function getOwnRouteContext(context: IContext): IParams;
26
26
  export declare function generateRoutePath(appView: IAppView, route: Route, context: IContext, params?: IParams | undefined): {
27
27
  path: string;
28
28
  };
29
- /**
30
- * 获取视图模型的codeName(小写)
31
- *
32
- * @export
33
- * @param {IAppView} model
34
- * @returns {*}
35
- */
36
- export declare function getViewName(model: IAppView): string;
37
- /**
38
- * 在单个应用里
39
- * 通过视图的codeName找到视图模型
40
- *
41
- * @param {(IApplication | ISubAppRef)} appModel 主应用或子应用
42
- * @param {string} viewCodeName 视图名称小写
43
- * @returns {*}
44
- */
45
- export declare function findViewByName(_appModel: IApplication, _viewCodeName: string): undefined;
46
- /**
47
- * 从子应用和主应用里
48
- * 通过视图的codeName找视图模型
49
- *
50
- * @param {IApplication} appModel 主应用
51
- * @param {string} viewCodeName 视图名称小写
52
- * @returns {*}
53
- */
54
- export declare function findView(_appModel: IApplication, _viewCodeName: string): undefined;
55
29
  /**
56
30
  * 解析路由获取对应视图数据
57
31
  *
@@ -60,10 +34,10 @@ export declare function findView(_appModel: IApplication, _viewCodeName: string)
60
34
  * @export
61
35
  * @param {IApplication} appModel 视图模型
62
36
  * @param {Route} route 路由对象
63
- * @param {number} level 层级
37
+ * @param {number} depth 层级
64
38
  * @returns {*} {IRouteViewData}
65
39
  */
66
- export declare function parseRouteViewData(route: Route, level: number): Promise<IRouteViewData>;
40
+ export declare function parseRouteViewData(route: Route, depth: number): Promise<IRouteViewData>;
67
41
  /**
68
42
  * 路径字符串转换成路由路径对象
69
43
  *
@@ -84,4 +58,16 @@ export declare function route2routePath(route: Route): IRoutePath;
84
58
  * @returns {*} {string}
85
59
  */
86
60
  export declare function routePath2string(routePath: IRoutePath): string;
61
+ /**
62
+ * 监听路由的变更,每次变更后都会触发回调
63
+ * 回调函数提供根据视图层级计算好的唯一标识currentKey,只有变了视图才需要刷新
64
+ * @author lxm
65
+ * @date 2023-05-09 12:52:36
66
+ * @param {(args: { currentKey: string; fullPath: string }) => void} callback
67
+ * @param {number} depth
68
+ */
69
+ export declare function onRouteChange(callback: (args: {
70
+ currentKey: string;
71
+ fullPath: string;
72
+ }) => void, depth: number): void;
87
73
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../src/util/route/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EAAE,6BAA6B,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,UAAU,EAAkB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAS7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,QAAQ,EACjB,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAiElB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,UAE1C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,aAAa,EAAE,MAAM,GACpB,SAAS,CAKX;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,YAAY,EACvB,aAAa,EAAE,MAAM,GACpB,SAAS,CAwBX;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CAkDzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CA+DxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAyC9D"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../../src/util/route/route.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,6BAA6B,IAAI,KAAK,EAAY,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,UAAU,EAAkB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAS7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,QAAQ,EACjB,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,GAC3B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAiElB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,cAAc,CAAC,CAkDzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,UAAU,CA+DxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAyC9D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,CAAC,IAAI,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,EAClE,KAAK,EAAE,MAAM,QAmBd"}
@@ -1,6 +1,8 @@
1
1
  import { notNilEmpty } from 'qx-util';
2
2
  import { RuntimeError } from '@ibiz-template/core';
3
3
  import qs from 'qs';
4
+ import { useRoute } from 'vue-router';
5
+ import { watch } from 'vue';
4
6
  /**
5
7
  * 获取自身的路由上下文,排除了部分不需要路由携带的参数
6
8
  *
@@ -12,7 +14,7 @@ import qs from 'qs';
12
14
  */
13
15
  export function getOwnRouteContext(context) {
14
16
  const ownContext = context.getOwnContext();
15
- const excludeKeys = ['srfsessionid'];
17
+ const excludeKeys = ['srfsessionid', 'srfappid'];
16
18
  Object.keys(ownContext).forEach(key => {
17
19
  if (excludeKeys.includes(key)) {
18
20
  delete ownContext[key];
@@ -34,15 +36,15 @@ export function getOwnRouteContext(context) {
34
36
  */
35
37
  export function generateRoutePath(appView, route, context, params) {
36
38
  const routePath = route2routePath(route);
37
- // 如果上下文存在toRouteLevel时,使用上下文的层级,否则是第二级路由
38
- let level = 2;
39
- if (context.toRouteLevel) {
40
- level = context.toRouteLevel;
39
+ // 如果上下文存在toRouteDepth时,使用上下文的层级,否则是第二级路由
40
+ let depth = 2;
41
+ if (context.toRouteDepth) {
42
+ depth = context.toRouteDepth;
41
43
  // 使用完后删除,避免添加到首页上下文里
42
- delete context.toRouteLevel;
44
+ delete context.toRouteDepth;
43
45
  }
44
46
  // 删除目标层级和之后的路由,保留之前层级的路由
45
- routePath.pathNodes.splice(level - 1, routePath.pathNodes.length - level + 1);
47
+ routePath.pathNodes.splice(depth - 1, routePath.pathNodes.length - depth + 1);
46
48
  // 导航视图的导航参数,加在目标层级之前的一个层级的视图参数里
47
49
  if (context.currentSrfNav) {
48
50
  const currentNode = routePath.pathNodes[routePath.pathNodes.length - 1];
@@ -69,7 +71,7 @@ export function generateRoutePath(appView, route, context, params) {
69
71
  });
70
72
  // 计算二级视图的资源路径加到index后面
71
73
  // const codeName = appView.getPSAppDataEntity()?.codeName;
72
- // if (level === 2 && codeName) {
74
+ // if (depth === 2 && codeName) {
73
75
  // const app = ibiz.hub.getApp(appView.getPSModelService().app);
74
76
  // const paths = app.resourcePathUtil.calcPaths(codeName);
75
77
  // const resContext = calcRouteContext(context, paths);
@@ -77,7 +79,7 @@ export function generateRoutePath(appView, route, context, params) {
77
79
  // // 资源路径不为空,二级视图的上下文删掉多余的资源上下文
78
80
  // routePath.pathNodes[0].context = resContext;
79
81
  // Object.keys(resContext).forEach(key => {
80
- // const currentNode = routePath.pathNodes[level - 1];
82
+ // const currentNode = routePath.pathNodes[depth - 1];
81
83
  // if (
82
84
  // currentNode.context &&
83
85
  // Object.prototype.hasOwnProperty.call(currentNode.context, key)
@@ -92,63 +94,6 @@ export function generateRoutePath(appView, route, context, params) {
92
94
  // 视图参数通过query传递
93
95
  return { path: routePath2string(routePath) };
94
96
  }
95
- /**
96
- * 获取视图模型的codeName(小写)
97
- *
98
- * @export
99
- * @param {IAppView} model
100
- * @returns {*}
101
- */
102
- export function getViewName(model) {
103
- return model.codeName.toLowerCase();
104
- }
105
- /**
106
- * 在单个应用里
107
- * 通过视图的codeName找到视图模型
108
- *
109
- * @param {(IApplication | ISubAppRef)} appModel 主应用或子应用
110
- * @param {string} viewCodeName 视图名称小写
111
- * @returns {*}
112
- */
113
- export function findViewByName(_appModel, _viewCodeName) {
114
- // return appModel.getAllPSAppViews()?.find((model: IAppView) => {
115
- // return getViewName(model) === viewCodeName;
116
- // });
117
- return undefined;
118
- }
119
- /**
120
- * 从子应用和主应用里
121
- * 通过视图的codeName找视图模型
122
- *
123
- * @param {IApplication} appModel 主应用
124
- * @param {string} viewCodeName 视图名称小写
125
- * @returns {*}
126
- */
127
- export function findView(_appModel, _viewCodeName) {
128
- // let viewModel: IAppView | null | undefined;
129
- // viewCodeName = viewCodeName.toLowerCase();
130
- // // index找默认首页视图,其他匹配codeName
131
- // if (viewCodeName === 'index') {
132
- // viewModel = appModel.getDefaultPSAppIndexView();
133
- // } else {
134
- // // 先查找子应用,找到则不继续找了,优先从最后面的子应用找起
135
- // if (appModel.getAllPSSubAppRefs()?.length) {
136
- // appModel
137
- // .getAllPSSubAppRefs()!
138
- // .reverse()
139
- // .find(sub => {
140
- // viewModel = findViewByName(sub, viewCodeName);
141
- // return !!viewModel;
142
- // });
143
- // }
144
- // // 子应用里没有就在主应用里找。
145
- // if (!viewModel) {
146
- // viewModel = findViewByName(appModel, viewCodeName);
147
- // }
148
- // }
149
- // return viewModel;
150
- return undefined;
151
- }
152
97
  /**
153
98
  * 解析路由获取对应视图数据
154
99
  *
@@ -157,17 +102,17 @@ export function findView(_appModel, _viewCodeName) {
157
102
  * @export
158
103
  * @param {IApplication} appModel 视图模型
159
104
  * @param {Route} route 路由对象
160
- * @param {number} level 层级
105
+ * @param {number} depth 层级
161
106
  * @returns {*} {IRouteViewData}
162
107
  */
163
- export async function parseRouteViewData(route, level) {
108
+ export async function parseRouteViewData(route, depth) {
164
109
  var _a;
165
110
  // 解析路由的视图参数
166
111
  const routePath = route2routePath(route);
167
112
  // 获取对应层级的视图名称参数
168
- let viewCodeName = routePath.pathNodes[level - 1].viewName;
113
+ let viewCodeName = routePath.pathNodes[depth - 1].viewName;
169
114
  if (!viewCodeName) {
170
- throw new RuntimeError(`第${level}级路由不存在视图标识`);
115
+ throw new RuntimeError(`第${depth}级路由不存在视图标识`);
171
116
  }
172
117
  if (viewCodeName === 'index') {
173
118
  viewCodeName = ibiz.hub.defaultAppIndexViewName;
@@ -190,14 +135,14 @@ export async function parseRouteViewData(route, level) {
190
135
  Object.assign(context, routePath.appContext);
191
136
  }
192
137
  // 逐层合并视图上下文
193
- for (let index = 0; index < level; index++) {
138
+ for (let index = 0; index < depth; index++) {
194
139
  const pathNode = routePath.pathNodes[index];
195
140
  if (notNilEmpty(pathNode.context)) {
196
141
  Object.assign(context, pathNode.context);
197
142
  }
198
143
  }
199
144
  // 最后一级路由对应的视图才会解析视图参数
200
- const { params, srfnav } = routePath.pathNodes[level - 1];
145
+ const { params, srfnav } = routePath.pathNodes[depth - 1];
201
146
  return {
202
147
  viewModel,
203
148
  context,
@@ -216,10 +161,10 @@ export async function parseRouteViewData(route, level) {
216
161
  */
217
162
  export function route2routePath(route) {
218
163
  // 一共匹配了几级路由
219
- const level = route.matched.length;
164
+ const depth = route.matched.length;
220
165
  // 解析路径节点
221
166
  const pathNodes = [];
222
- for (let index = 1; index <= level; index++) {
167
+ for (let index = 1; index <= depth; index++) {
223
168
  const viewName = route.params[`view${index}`];
224
169
  const paramsStr = route.params[`params${index}`];
225
170
  /** 路由参数,默认是视图参数 */
@@ -321,3 +266,26 @@ export function routePath2string(routePath) {
321
266
  });
322
267
  return pathStr;
323
268
  }
269
+ /**
270
+ * 监听路由的变更,每次变更后都会触发回调
271
+ * 回调函数提供根据视图层级计算好的唯一标识currentKey,只有变了视图才需要刷新
272
+ * @author lxm
273
+ * @date 2023-05-09 12:52:36
274
+ * @param {(args: { currentKey: string; fullPath: string }) => void} callback
275
+ * @param {number} depth
276
+ */
277
+ export function onRouteChange(callback, depth) {
278
+ const route = useRoute();
279
+ watch(() => route.path, () => {
280
+ const routePath = route2routePath(route);
281
+ let currentKey = '';
282
+ if (routePath.pathNodes.length >= depth) {
283
+ // 删除depth后面的节点
284
+ routePath.pathNodes = routePath.pathNodes.slice(0, depth);
285
+ // 删除自身的srfnav
286
+ delete routePath.pathNodes[depth - 1].srfnav;
287
+ currentKey = routePath2string(routePath);
288
+ }
289
+ callback({ currentKey, fullPath: route.fullPath });
290
+ }, { immediate: true });
291
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibiz-template/vue3-util",
3
- "version": "0.0.4-beta.3",
3
+ "version": "0.0.4-beta.5",
4
4
  "description": "vue3 工具包",
5
5
  "type": "module",
6
6
  "main": "out/index.js",
@@ -29,8 +29,8 @@
29
29
  "author": "chitanda",
30
30
  "license": "MIT",
31
31
  "devDependencies": {
32
- "@ibiz-template/core": "^0.0.4-beta.3",
33
- "@ibiz-template/runtime": "^0.0.4-beta.3",
32
+ "@ibiz-template/core": "^0.0.4-beta.5",
33
+ "@ibiz-template/runtime": "^0.0.4-beta.5",
34
34
  "@ibiz/model-core": "^0.0.6",
35
35
  "@types/qs": "^6.9.7",
36
36
  "qs": "^6.11.1",
@@ -49,5 +49,5 @@
49
49
  "vue": "^3.2.47",
50
50
  "vue-router": "^4.1.6"
51
51
  },
52
- "gitHead": "78d7e7c4cf7521133c32205593fbfa0b5adac9e6"
52
+ "gitHead": "899c34a41e55998a64d331fcf8ea28c94d1fdbce"
53
53
  }
@@ -1,5 +1,12 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
1
2
  import { CTX, ViewController } from '@ibiz-template/runtime';
2
- import { inject, onBeforeUnmount, provide, reactive } from 'vue';
3
+ import {
4
+ getCurrentInstance,
5
+ inject,
6
+ onBeforeUnmount,
7
+ provide,
8
+ reactive,
9
+ } from 'vue';
3
10
  import { useForce, useProps } from '../../vue/vue';
4
11
 
5
12
  /**
@@ -24,17 +31,22 @@ export function useViewController<T extends ViewController>(
24
31
  ctx?.evt.emit('forecast', props.modelData.name!);
25
32
  const c = fn(props.modelData, props.context, props.params, ctx);
26
33
  // 提供自身的ctx给下层组件
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
34
  provide('ctx', (c as any).ctx);
29
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
+ // 让state 响应式
30
36
  c.state = reactive(c.state) as any;
31
37
  // 从props赋值modal,如果存在的话。
32
38
  if (props.modal) {
33
39
  c.modal = props.modal;
34
40
  }
35
41
 
42
+ const vue = getCurrentInstance()!.proxy!;
43
+
36
44
  c.force = useForce();
37
45
 
46
+ c.evt.onAll((eventName, event) => {
47
+ vue.$emit(eventName.slice(2), event);
48
+ });
49
+
38
50
  c.created();
39
51
 
40
52
  // 卸载时销毁
@@ -1,5 +1,5 @@
1
1
  import { ControlController, CTX } from '@ibiz-template/runtime';
2
- import { inject, onBeforeUnmount, reactive } from 'vue';
2
+ import { getCurrentInstance, inject, onBeforeUnmount, reactive } from 'vue';
3
3
  import { useForce, useProps } from '../../vue/vue';
4
4
 
5
5
  /**
@@ -26,6 +26,12 @@ export function useControlController<T extends ControlController>(
26
26
 
27
27
  c.force = useForce();
28
28
 
29
+ const vue = getCurrentInstance()!.proxy!;
30
+
31
+ c.evt.onAll((eventName, event) => {
32
+ vue.$emit(eventName, event);
33
+ });
34
+
29
35
  c.created();
30
36
 
31
37
  // 挂载强制更新方法
package/src/util/index.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './route/route';
2
2
  export * from './route/route-listener';
3
+ export * from './install';
@@ -0,0 +1,11 @@
1
+ /* eslint-disable no-param-reassign */
2
+ import type { App, Plugin } from 'vue';
3
+
4
+ export type TypeWithInstall<T> = T & Plugin;
5
+
6
+ export const withInstall = <T>(main: T, install: (_v: App) => void) => {
7
+ (main as TypeWithInstall<T>).install = (app): void => {
8
+ install(app);
9
+ };
10
+ return main as TypeWithInstall<T>;
11
+ };
@@ -1,8 +1,9 @@
1
1
  import { notNilEmpty } from 'qx-util';
2
2
  import { RuntimeError } from '@ibiz-template/core';
3
- import { IApplication, IAppView } from '@ibiz/model-core';
3
+ import { IAppView } from '@ibiz/model-core';
4
4
  import qs from 'qs';
5
- import { RouteLocationNormalizedLoaded as Route } from 'vue-router';
5
+ import { RouteLocationNormalizedLoaded as Route, useRoute } from 'vue-router';
6
+ import { watch } from 'vue';
6
7
  import { IRoutePath, IRoutePathNode, IRouteViewData } from '../../interface';
7
8
 
8
9
  /**
@@ -16,7 +17,7 @@ import { IRoutePath, IRoutePathNode, IRouteViewData } from '../../interface';
16
17
  */
17
18
  export function getOwnRouteContext(context: IContext): IParams {
18
19
  const ownContext = context.getOwnContext();
19
- const excludeKeys = ['srfsessionid'];
20
+ const excludeKeys = ['srfsessionid', 'srfappid'];
20
21
  Object.keys(ownContext).forEach(key => {
21
22
  if (excludeKeys.includes(key)) {
22
23
  delete ownContext[key];
@@ -44,16 +45,16 @@ export function generateRoutePath(
44
45
  params?: IParams | undefined,
45
46
  ): { path: string } {
46
47
  const routePath = route2routePath(route);
47
- // 如果上下文存在toRouteLevel时,使用上下文的层级,否则是第二级路由
48
- let level = 2;
49
- if (context.toRouteLevel) {
50
- level = context.toRouteLevel;
48
+ // 如果上下文存在toRouteDepth时,使用上下文的层级,否则是第二级路由
49
+ let depth = 2;
50
+ if (context.toRouteDepth) {
51
+ depth = context.toRouteDepth;
51
52
  // 使用完后删除,避免添加到首页上下文里
52
- delete context.toRouteLevel;
53
+ delete context.toRouteDepth;
53
54
  }
54
55
 
55
56
  // 删除目标层级和之后的路由,保留之前层级的路由
56
- routePath.pathNodes.splice(level - 1, routePath.pathNodes.length - level + 1);
57
+ routePath.pathNodes.splice(depth - 1, routePath.pathNodes.length - depth + 1);
57
58
 
58
59
  // 导航视图的导航参数,加在目标层级之前的一个层级的视图参数里
59
60
  if (context.currentSrfNav) {
@@ -83,7 +84,7 @@ export function generateRoutePath(
83
84
 
84
85
  // 计算二级视图的资源路径加到index后面
85
86
  // const codeName = appView.getPSAppDataEntity()?.codeName;
86
- // if (level === 2 && codeName) {
87
+ // if (depth === 2 && codeName) {
87
88
  // const app = ibiz.hub.getApp(appView.getPSModelService().app);
88
89
  // const paths = app.resourcePathUtil.calcPaths(codeName);
89
90
  // const resContext = calcRouteContext(context, paths);
@@ -91,7 +92,7 @@ export function generateRoutePath(
91
92
  // // 资源路径不为空,二级视图的上下文删掉多余的资源上下文
92
93
  // routePath.pathNodes[0].context = resContext;
93
94
  // Object.keys(resContext).forEach(key => {
94
- // const currentNode = routePath.pathNodes[level - 1];
95
+ // const currentNode = routePath.pathNodes[depth - 1];
95
96
  // if (
96
97
  // currentNode.context &&
97
98
  // Object.prototype.hasOwnProperty.call(currentNode.context, key)
@@ -109,72 +110,6 @@ export function generateRoutePath(
109
110
  return { path: routePath2string(routePath) };
110
111
  }
111
112
 
112
- /**
113
- * 获取视图模型的codeName(小写)
114
- *
115
- * @export
116
- * @param {IAppView} model
117
- * @returns {*}
118
- */
119
- export function getViewName(model: IAppView) {
120
- return model.codeName!.toLowerCase();
121
- }
122
-
123
- /**
124
- * 在单个应用里
125
- * 通过视图的codeName找到视图模型
126
- *
127
- * @param {(IApplication | ISubAppRef)} appModel 主应用或子应用
128
- * @param {string} viewCodeName 视图名称小写
129
- * @returns {*}
130
- */
131
- export function findViewByName(
132
- _appModel: IApplication,
133
- _viewCodeName: string,
134
- ): undefined {
135
- // return appModel.getAllPSAppViews()?.find((model: IAppView) => {
136
- // return getViewName(model) === viewCodeName;
137
- // });
138
- return undefined;
139
- }
140
-
141
- /**
142
- * 从子应用和主应用里
143
- * 通过视图的codeName找视图模型
144
- *
145
- * @param {IApplication} appModel 主应用
146
- * @param {string} viewCodeName 视图名称小写
147
- * @returns {*}
148
- */
149
- export function findView(
150
- _appModel: IApplication,
151
- _viewCodeName: string,
152
- ): undefined {
153
- // let viewModel: IAppView | null | undefined;
154
- // viewCodeName = viewCodeName.toLowerCase();
155
- // // index找默认首页视图,其他匹配codeName
156
- // if (viewCodeName === 'index') {
157
- // viewModel = appModel.getDefaultPSAppIndexView();
158
- // } else {
159
- // // 先查找子应用,找到则不继续找了,优先从最后面的子应用找起
160
- // if (appModel.getAllPSSubAppRefs()?.length) {
161
- // appModel
162
- // .getAllPSSubAppRefs()!
163
- // .reverse()
164
- // .find(sub => {
165
- // viewModel = findViewByName(sub, viewCodeName);
166
- // return !!viewModel;
167
- // });
168
- // }
169
- // // 子应用里没有就在主应用里找。
170
- // if (!viewModel) {
171
- // viewModel = findViewByName(appModel, viewCodeName);
172
- // }
173
- // }
174
- // return viewModel;
175
- return undefined;
176
- }
177
-
178
113
  /**
179
114
  * 解析路由获取对应视图数据
180
115
  *
@@ -183,20 +118,20 @@ export function findView(
183
118
  * @export
184
119
  * @param {IApplication} appModel 视图模型
185
120
  * @param {Route} route 路由对象
186
- * @param {number} level 层级
121
+ * @param {number} depth 层级
187
122
  * @returns {*} {IRouteViewData}
188
123
  */
189
124
  export async function parseRouteViewData(
190
125
  route: Route,
191
- level: number,
126
+ depth: number,
192
127
  ): Promise<IRouteViewData> {
193
128
  // 解析路由的视图参数
194
129
  const routePath = route2routePath(route);
195
130
 
196
131
  // 获取对应层级的视图名称参数
197
- let viewCodeName = routePath.pathNodes[level - 1].viewName;
132
+ let viewCodeName = routePath.pathNodes[depth - 1].viewName;
198
133
  if (!viewCodeName) {
199
- throw new RuntimeError(`第${level}级路由不存在视图标识`);
134
+ throw new RuntimeError(`第${depth}级路由不存在视图标识`);
200
135
  }
201
136
  if (viewCodeName === 'index') {
202
137
  viewCodeName = ibiz.hub.defaultAppIndexViewName;
@@ -223,7 +158,7 @@ export async function parseRouteViewData(
223
158
  Object.assign(context, routePath.appContext);
224
159
  }
225
160
  // 逐层合并视图上下文
226
- for (let index = 0; index < level; index++) {
161
+ for (let index = 0; index < depth; index++) {
227
162
  const pathNode = routePath.pathNodes[index];
228
163
  if (notNilEmpty(pathNode.context)) {
229
164
  Object.assign(context, pathNode.context);
@@ -231,7 +166,7 @@ export async function parseRouteViewData(
231
166
  }
232
167
 
233
168
  // 最后一级路由对应的视图才会解析视图参数
234
- const { params, srfnav } = routePath.pathNodes[level - 1];
169
+ const { params, srfnav } = routePath.pathNodes[depth - 1];
235
170
 
236
171
  return {
237
172
  viewModel,
@@ -252,11 +187,11 @@ export async function parseRouteViewData(
252
187
  */
253
188
  export function route2routePath(route: Route): IRoutePath {
254
189
  // 一共匹配了几级路由
255
- const level = route.matched.length;
190
+ const depth = route.matched.length;
256
191
 
257
192
  // 解析路径节点
258
193
  const pathNodes: IRoutePathNode[] = [];
259
- for (let index = 1; index <= level; index++) {
194
+ for (let index = 1; index <= depth; index++) {
260
195
  const viewName = route.params[`view${index}`] as string;
261
196
  const paramsStr = route.params[`params${index}`] as string;
262
197
 
@@ -366,3 +301,34 @@ export function routePath2string(routePath: IRoutePath): string {
366
301
 
367
302
  return pathStr;
368
303
  }
304
+
305
+ /**
306
+ * 监听路由的变更,每次变更后都会触发回调
307
+ * 回调函数提供根据视图层级计算好的唯一标识currentKey,只有变了视图才需要刷新
308
+ * @author lxm
309
+ * @date 2023-05-09 12:52:36
310
+ * @param {(args: { currentKey: string; fullPath: string }) => void} callback
311
+ * @param {number} depth
312
+ */
313
+ export function onRouteChange(
314
+ callback: (args: { currentKey: string; fullPath: string }) => void,
315
+ depth: number,
316
+ ) {
317
+ const route = useRoute();
318
+ watch(
319
+ () => route.path,
320
+ () => {
321
+ const routePath = route2routePath(route);
322
+ let currentKey = '';
323
+ if (routePath.pathNodes.length >= depth) {
324
+ // 删除depth后面的节点
325
+ routePath.pathNodes = routePath.pathNodes.slice(0, depth);
326
+ // 删除自身的srfnav
327
+ delete routePath.pathNodes[depth - 1].srfnav;
328
+ currentKey = routePath2string(routePath);
329
+ }
330
+ callback({ currentKey, fullPath: route.fullPath });
331
+ },
332
+ { immediate: true },
333
+ );
334
+ }