@deppon/deppon-template 2.5.4 → 2.5.6

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/es/index.d.ts CHANGED
@@ -3,5 +3,24 @@ export { default as ProForm } from './pro-form';
3
3
  export { default as ProTable } from './pro-table';
4
4
  export { default as ProLayout } from './pro-layout';
5
5
  export { default as ProDialog } from './pro-dialog';
6
- export { ProIframe, ProIframeRouteView, createIframeRoute, buildIframeRouteLocation, resolveIframeSrcFromRoute, appendQueryToUrl, isIframeRoute, decodeIframeUrlValue, applyIframeUrlTemplate, resolveDynamicIframeBaseUrl, PRO_IFRAME_URL_QUERY_KEYS, PRO_IFRAME_URL_RESERVED_QUERY_KEYS, isInIframeEmbed, } from './pro-iframe';
7
- export type { ProIframeRouteMeta, ProIframeProps, CreateIframeRouteOptions, BuildIframeRouteLocationOptions, } from './pro-iframe';
6
+ export {
7
+ ProIframe,
8
+ ProIframeRouteView,
9
+ createIframeRoute,
10
+ buildIframeRouteLocation,
11
+ resolveIframeSrcFromRoute,
12
+ appendQueryToUrl,
13
+ isIframeRoute,
14
+ decodeIframeUrlValue,
15
+ applyIframeUrlTemplate,
16
+ resolveDynamicIframeBaseUrl,
17
+ PRO_IFRAME_URL_QUERY_KEYS,
18
+ PRO_IFRAME_URL_RESERVED_QUERY_KEYS,
19
+ isInIframeEmbed,
20
+ } from './pro-iframe';
21
+ export type {
22
+ ProIframeRouteMeta,
23
+ ProIframeProps,
24
+ CreateIframeRouteOptions,
25
+ BuildIframeRouteLocationOptions,
26
+ } from './pro-iframe';
@@ -1,4 +1,6 @@
1
- export { default as ProField } from './ProField';
2
- export { default as ProFieldText } from './components/Text/index';
3
- export { default as ProFieldSelect } from './components/Select/index';
4
- export { default as ProFieldDatePicker } from './components/DatePicker/index';
1
+ import type { DefineComponent } from 'vue';
2
+
3
+ export declare const ProField: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
4
+ export declare const ProFieldText: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
5
+ export declare const ProFieldSelect: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
6
+ export declare const ProFieldDatePicker: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
@@ -7,12 +7,14 @@
7
7
  background: var(--el-bg-color, #fff);
8
8
  }
9
9
  .pro-iframe--full {
10
+ flex: 1;
10
11
  height: 100%;
11
12
  min-height: 0;
12
13
  }
13
14
  .pro-iframe__toolbar {
14
15
  flex-shrink: 0;
15
- padding: 8px 12px;
16
+ padding: 6px 12px;
17
+ background: var(--el-fill-color-blank, #fff);
16
18
  border-bottom: 1px solid var(--el-border-color-lighter, #ebeef5);
17
19
  }
18
20
  .pro-iframe__body {
@@ -6,6 +6,7 @@ import { useRoute } from '@deppon/deppon-router';
6
6
  import { ElEmpty, ElButton } from '@deppon/deppon-ui';
7
7
  import { initIframeStyleFix } from '@deppon/deppon-utils';
8
8
  import { appendQueryToUrl, PRO_IFRAME_URL_RESERVED_QUERY_KEYS } from './resolveIframeSrc.js';
9
+ import { installIframeHostBridge } from './iframeHostBridge.js';
9
10
 
10
11
  var _hoisted_1 = {
11
12
  key: 0,
@@ -95,6 +96,16 @@ var script = {
95
96
  loadTimeout: {
96
97
  type: Number,
97
98
  "default": 30000
99
+ },
100
+ /** 壳层路由 fullPath,用于同源子页通过 deppon-router 关闭/新开 ProLayout 页签 */
101
+ shellTabKey: {
102
+ type: String,
103
+ "default": ''
104
+ },
105
+ /** iframe load 后向同源子页注入 __DEPPON_IFRAME_HOST__(对齐 Ext viewTab 宿主) */
106
+ bridgeRouterTab: {
107
+ type: Boolean,
108
+ "default": true
98
109
  }
99
110
  },
100
111
  emits: ['load', 'error', 'src-change'],
@@ -179,10 +190,17 @@ var script = {
179
190
  }, {
180
191
  immediate: true
181
192
  });
193
+ function syncIframeHostBridge() {
194
+ if (!props.bridgeRouterTab || !props.shellTabKey || !iframeRef.value) {
195
+ return;
196
+ }
197
+ installIframeHostBridge(iframeRef.value.contentWindow, props.shellTabKey);
198
+ }
182
199
  function handleLoad() {
183
200
  clearLoadTimeout();
184
201
  frameLoading.value = false;
185
202
  loadError.value = false;
203
+ syncIframeHostBridge();
186
204
  emit('load', iframeRef.value);
187
205
  }
188
206
  function handleError() {
@@ -197,6 +215,34 @@ var script = {
197
215
  scheduleLoadTimeout();
198
216
  reloadToken.value += 1;
199
217
  }
218
+ function getIframeWindow() {
219
+ try {
220
+ var _iframeRef$value$cont, _iframeRef$value;
221
+ return (_iframeRef$value$cont = (_iframeRef$value = iframeRef.value) === null || _iframeRef$value === void 0 ? void 0 : _iframeRef$value.contentWindow) !== null && _iframeRef$value$cont !== void 0 ? _iframeRef$value$cont : null;
222
+ } catch (_unused) {
223
+ return null;
224
+ }
225
+ }
226
+
227
+ /** 后退(跨域时由浏览器执行,可能无历史记录则无效果) */
228
+ function goBack() {
229
+ try {
230
+ var _getIframeWindow;
231
+ (_getIframeWindow = getIframeWindow()) === null || _getIframeWindow === void 0 || _getIframeWindow.history.back();
232
+ } catch (_unused2) {
233
+ /* cross-origin */
234
+ }
235
+ }
236
+
237
+ /** 前进 */
238
+ function goForward() {
239
+ try {
240
+ var _getIframeWindow2;
241
+ (_getIframeWindow2 = getIframeWindow()) === null || _getIframeWindow2 === void 0 || _getIframeWindow2.history.forward();
242
+ } catch (_unused3) {
243
+ /* cross-origin */
244
+ }
245
+ }
200
246
  onMounted(function () {
201
247
  if (props.fixParentStyle) {
202
248
  initIframeStyleFix();
@@ -207,6 +253,8 @@ var script = {
207
253
  });
208
254
  __expose({
209
255
  reload: reload,
256
+ goBack: goBack,
257
+ goForward: goForward,
210
258
  iframeRef: iframeRef,
211
259
  effectiveSrc: effectiveSrc
212
260
  });
@@ -217,7 +265,9 @@ var script = {
217
265
  }])
218
266
  }, [_ctx.$slots.toolbar ? (openBlock(), createElementBlock("div", _hoisted_1, [renderSlot(_ctx.$slots, "toolbar", {
219
267
  reload: reload,
220
- src: effectiveSrc.value
268
+ src: effectiveSrc.value,
269
+ goBack: goBack,
270
+ goForward: goForward
221
271
  })])) : createCommentVNode("v-if", true), createElementVNode("div", _hoisted_2, [effectiveSrc.value ? (openBlock(), createElementBlock("iframe", {
222
272
  key: effectiveSrc.value,
223
273
  ref_key: "iframeRef",
@@ -0,0 +1,69 @@
1
+ .pro-iframe-default-toolbar {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 12px;
5
+ width: 100%;
6
+ min-height: 36px;
7
+ }
8
+ .pro-iframe-default-toolbar__nav {
9
+ display: flex;
10
+ flex-shrink: 0;
11
+ align-items: center;
12
+ gap: 2px;
13
+ padding: 3px 4px;
14
+ background: var(--el-fill-color-light, #f5f7fa);
15
+ border: 1px solid var(--el-border-color-lighter, #ebeef5);
16
+ border-radius: 8px;
17
+ }
18
+ .pro-iframe-default-toolbar__divider {
19
+ flex-shrink: 0;
20
+ width: 1px;
21
+ height: 18px;
22
+ margin: 0 2px;
23
+ background: var(--el-border-color-lighter, #e4e7ed);
24
+ }
25
+ .pro-iframe-default-toolbar__btn {
26
+ width: 28px !important;
27
+ height: 28px !important;
28
+ padding: 0 !important;
29
+ color: var(--el-text-color-regular, #606266) !important;
30
+ }
31
+ .pro-iframe-default-toolbar__btn:hover {
32
+ color: var(--el-color-primary, #409eff) !important;
33
+ background: var(--el-fill-color, #f0f2f5) !important;
34
+ }
35
+ .pro-iframe-default-toolbar__info {
36
+ display: flex;
37
+ flex: 1;
38
+ flex-direction: column;
39
+ justify-content: center;
40
+ gap: 2px;
41
+ min-width: 0;
42
+ padding: 2px 8px;
43
+ background: var(--el-fill-color-lighter, #fafafa);
44
+ border: 1px solid var(--el-border-color-extra-light, #f2f3f5);
45
+ border-radius: 6px;
46
+ }
47
+ .pro-iframe-default-toolbar__title {
48
+ font-size: 13px;
49
+ font-weight: 600;
50
+ line-height: 1.3;
51
+ color: var(--el-text-color-primary, #303133);
52
+ overflow: hidden;
53
+ text-overflow: ellipsis;
54
+ white-space: nowrap;
55
+ }
56
+ .pro-iframe-default-toolbar__url {
57
+ font-size: 12px;
58
+ line-height: 1.3;
59
+ color: var(--el-text-color-secondary, #909399);
60
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
61
+ overflow: hidden;
62
+ text-overflow: ellipsis;
63
+ white-space: nowrap;
64
+ }
65
+ .pro-iframe-default-toolbar__extra {
66
+ display: flex;
67
+ flex-shrink: 0;
68
+ align-items: center;
69
+ }
@@ -0,0 +1,7 @@
1
+ import '../_virtual/_rollup-plugin-inject-process-env.js';
2
+ import script from './ProIframeDefaultToolbar.vue_vue_type_script_setup_true_lang.vue.js';
3
+ export { default } from './ProIframeDefaultToolbar.vue_vue_type_script_setup_true_lang.vue.js';
4
+ import './ProIframeDefaultToolbar.vue_vue_type_style_index_0_id_0c49bbb7_scoped_true_lang.vue.js';
5
+
6
+ script.__scopeId = "data-v-0c49bbb7";
7
+ script.__file = "packages/deppon-template/src/pro-iframe/ProIframeDefaultToolbar.vue";
@@ -0,0 +1,157 @@
1
+ import '../_virtual/_rollup-plugin-inject-process-env.js';
2
+ import { markRaw, computed, openBlock, createElementBlock, createElementVNode, createVNode, unref, withCtx, toDisplayString, createCommentVNode, createBlock } from 'vue';
3
+ import { ElTooltip, ElButton } from '@deppon/deppon-ui';
4
+ import { ArrowLeft, ArrowRight, RefreshRight, Link } from '@deppon/deppon-ui/icons-vue';
5
+
6
+ var _hoisted_1 = {
7
+ "class": "pro-iframe-default-toolbar"
8
+ };
9
+ var _hoisted_2 = {
10
+ "class": "pro-iframe-default-toolbar__nav"
11
+ };
12
+ var _hoisted_3 = {
13
+ "class": "pro-iframe-default-toolbar__info"
14
+ };
15
+ var _hoisted_4 = {
16
+ key: 0,
17
+ "class": "pro-iframe-default-toolbar__title"
18
+ };
19
+ var _hoisted_5 = ["title"];
20
+ var _hoisted_6 = {
21
+ "class": "pro-iframe-default-toolbar__extra"
22
+ };
23
+ var script = {
24
+ __name: 'ProIframeDefaultToolbar',
25
+ props: {
26
+ title: {
27
+ type: String,
28
+ "default": ''
29
+ },
30
+ src: {
31
+ type: String,
32
+ "default": ''
33
+ },
34
+ reload: {
35
+ type: Function,
36
+ "default": null
37
+ },
38
+ goBack: {
39
+ type: Function,
40
+ "default": null
41
+ },
42
+ goForward: {
43
+ type: Function,
44
+ "default": null
45
+ }
46
+ },
47
+ setup: function setup(__props) {
48
+ var ArrowLeftIcon = markRaw(ArrowLeft);
49
+ var ArrowRightIcon = markRaw(ArrowRight);
50
+ var RefreshIcon = markRaw(RefreshRight);
51
+ var LinkIcon = markRaw(Link);
52
+ var props = __props;
53
+ var displayUrl = computed(function () {
54
+ var raw = (props.src || '').trim();
55
+ if (!raw) return '';
56
+ try {
57
+ var parsed = new URL(raw);
58
+ var path = "".concat(parsed.pathname).concat(parsed.search).concat(parsed.hash);
59
+ return path || parsed.host;
60
+ } catch (_unused) {
61
+ return raw;
62
+ }
63
+ });
64
+ function handleReload() {
65
+ if (typeof props.reload === 'function') {
66
+ props.reload();
67
+ }
68
+ }
69
+ function handleGoBack() {
70
+ if (typeof props.goBack === 'function') {
71
+ props.goBack();
72
+ }
73
+ }
74
+ function handleGoForward() {
75
+ if (typeof props.goForward === 'function') {
76
+ props.goForward();
77
+ }
78
+ }
79
+ function handleOpen() {
80
+ if (!props.src || typeof window === 'undefined') return;
81
+ window.open(props.src, '_blank', 'noopener,noreferrer');
82
+ }
83
+ return function (_ctx, _cache) {
84
+ return openBlock(), createElementBlock("div", _hoisted_1, [createElementVNode("div", _hoisted_2, [createVNode(unref(ElTooltip), {
85
+ content: "后退",
86
+ placement: "bottom"
87
+ }, {
88
+ "default": withCtx(function () {
89
+ return [createVNode(unref(ElButton), {
90
+ text: "",
91
+ circle: "",
92
+ size: "small",
93
+ "class": "pro-iframe-default-toolbar__btn",
94
+ icon: unref(ArrowLeftIcon),
95
+ onClick: handleGoBack
96
+ }, null, 8 /* PROPS */, ["icon"])];
97
+ }),
98
+ _: 1 /* STABLE */
99
+ }), createVNode(unref(ElTooltip), {
100
+ content: "前进",
101
+ placement: "bottom"
102
+ }, {
103
+ "default": withCtx(function () {
104
+ return [createVNode(unref(ElButton), {
105
+ text: "",
106
+ circle: "",
107
+ size: "small",
108
+ "class": "pro-iframe-default-toolbar__btn",
109
+ icon: unref(ArrowRightIcon),
110
+ onClick: handleGoForward
111
+ }, null, 8 /* PROPS */, ["icon"])];
112
+ }),
113
+ _: 1 /* STABLE */
114
+ }), _cache[0] || (_cache[0] = createElementVNode("span", {
115
+ "class": "pro-iframe-default-toolbar__divider",
116
+ "aria-hidden": "true"
117
+ }, null, -1 /* CACHED */)), createVNode(unref(ElTooltip), {
118
+ content: "刷新",
119
+ placement: "bottom"
120
+ }, {
121
+ "default": withCtx(function () {
122
+ return [createVNode(unref(ElButton), {
123
+ text: "",
124
+ circle: "",
125
+ size: "small",
126
+ "class": "pro-iframe-default-toolbar__btn",
127
+ icon: unref(RefreshIcon),
128
+ onClick: handleReload
129
+ }, null, 8 /* PROPS */, ["icon"])];
130
+ }),
131
+ _: 1 /* STABLE */
132
+ })]), createElementVNode("div", _hoisted_3, [__props.title ? (openBlock(), createElementBlock("span", _hoisted_4, toDisplayString(__props.title), 1 /* TEXT */)) : createCommentVNode("v-if", true), displayUrl.value ? (openBlock(), createElementBlock("span", {
133
+ key: 1,
134
+ "class": "pro-iframe-default-toolbar__url",
135
+ title: displayUrl.value
136
+ }, toDisplayString(displayUrl.value), 9 /* TEXT, PROPS */, _hoisted_5)) : createCommentVNode("v-if", true)]), createElementVNode("div", _hoisted_6, [__props.src ? (openBlock(), createBlock(unref(ElTooltip), {
137
+ key: 0,
138
+ content: "新窗口打开",
139
+ placement: "bottom"
140
+ }, {
141
+ "default": withCtx(function () {
142
+ return [createVNode(unref(ElButton), {
143
+ text: "",
144
+ circle: "",
145
+ size: "small",
146
+ "class": "pro-iframe-default-toolbar__btn",
147
+ icon: unref(LinkIcon),
148
+ onClick: handleOpen
149
+ }, null, 8 /* PROPS */, ["icon"])];
150
+ }),
151
+ _: 1 /* STABLE */
152
+ })) : createCommentVNode("v-if", true)])]);
153
+ };
154
+ }
155
+ };
156
+
157
+ export { script as default };
@@ -0,0 +1 @@
1
+ import './ProIframeDefaultToolbar.vue.css';
@@ -0,0 +1,13 @@
1
+ .pro-iframe-route-view {
2
+ display: flex;
3
+ flex-direction: column;
4
+ width: 100%;
5
+ height: 100%;
6
+ min-height: 0;
7
+ box-sizing: border-box;
8
+ }
9
+ .pro-iframe-route-view .pro-iframe {
10
+ flex: 1;
11
+ min-height: 0;
12
+ height: 100%;
13
+ }
@@ -1,5 +1,7 @@
1
1
  import '../_virtual/_rollup-plugin-inject-process-env.js';
2
2
  import script from './ProIframeRouteView.vue_vue_type_script_setup_true_lang.vue.js';
3
3
  export { default } from './ProIframeRouteView.vue_vue_type_script_setup_true_lang.vue.js';
4
+ import './ProIframeRouteView.vue_vue_type_style_index_0_id_d2b52e3e_scoped_true_lang.vue.js';
4
5
 
6
+ script.__scopeId = "data-v-d2b52e3e";
5
7
  script.__file = "packages/deppon-template/src/pro-iframe/ProIframeRouteView.vue";
@@ -1,18 +1,29 @@
1
1
  import '../_virtual/_rollup-plugin-inject-process-env.js';
2
2
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
3
  import _typeof from '@babel/runtime/helpers/typeof';
4
- import { computed, openBlock, createBlock, mergeProps, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps } from 'vue';
4
+ import { computed, openBlock, createElementBlock, createBlock, mergeProps, unref, createSlots, withCtx, renderSlot, normalizeProps, guardReactiveProps, createVNode } from 'vue';
5
5
  import { useRoute } from '@deppon/deppon-router';
6
6
  import './ProIframe.vue.js';
7
+ import './ProIframeDefaultToolbar.vue.js';
7
8
  import { resolveIframeSrcFromRoute } from './resolveIframeSrc.js';
9
+ import script$2 from './ProIframeDefaultToolbar.vue_vue_type_script_setup_true_lang.vue.js';
8
10
  import script$1 from './ProIframe.vue_vue_type_script_setup_true_lang.vue.js';
9
11
 
10
12
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
13
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
14
+ var _hoisted_1 = {
15
+ "class": "pro-iframe-route-view"
16
+ };
12
17
  var script = {
13
18
  __name: 'ProIframeRouteView',
14
19
  setup: function setup(__props) {
15
20
  var route = useRoute();
21
+
22
+ /** 仅 meta.iframeToolbar === true 时展示内置 toolbar */
23
+ var showToolbar = computed(function () {
24
+ var _route$meta;
25
+ return ((_route$meta = route.meta) === null || _route$meta === void 0 ? void 0 : _route$meta.iframeToolbar) === true;
26
+ });
16
27
  var resolvedSrc = computed(function () {
17
28
  return resolveIframeSrcFromRoute(route);
18
29
  });
@@ -28,8 +39,8 @@ var script = {
28
39
  return q && String(q) || meta.title || meta.iframeTitle || '';
29
40
  });
30
41
  var fixParentStyle = computed(function () {
31
- var _route$meta;
32
- return Boolean((_route$meta = route.meta) === null || _route$meta === void 0 ? void 0 : _route$meta.iframeFixParentStyle);
42
+ var _route$meta2;
43
+ return Boolean((_route$meta2 = route.meta) === null || _route$meta2 === void 0 ? void 0 : _route$meta2.iframeFixParentStyle);
33
44
  });
34
45
  var iframeBindProps = computed(function () {
35
46
  var meta = route.meta || {};
@@ -44,19 +55,24 @@ var script = {
44
55
  }, extra);
45
56
  });
46
57
  return function (_ctx, _cache) {
47
- return openBlock(), createBlock(script$1, mergeProps({
58
+ return openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(), createBlock(script$1, mergeProps({
48
59
  key: resolvedSrc.value,
49
60
  src: resolvedSrc.value,
50
61
  name: iframeName.value,
51
62
  title: iframeTitle.value,
63
+ "shell-tab-key": unref(route).fullPath,
52
64
  "append-route-query": false,
53
65
  "fix-parent-style": fixParentStyle.value
54
66
  }, iframeBindProps.value), createSlots({
55
67
  _: 2 /* DYNAMIC */
56
- }, [_ctx.$slots.toolbar ? {
68
+ }, [showToolbar.value ? {
57
69
  name: "toolbar",
58
70
  fn: withCtx(function (slotProps) {
59
- return [renderSlot(_ctx.$slots, "toolbar", normalizeProps(guardReactiveProps(slotProps)))];
71
+ return [renderSlot(_ctx.$slots, "toolbar", normalizeProps(guardReactiveProps(slotProps)), function () {
72
+ return [createVNode(script$2, mergeProps(slotProps, {
73
+ title: iframeTitle.value
74
+ }), null, 16 /* FULL_PROPS */, ["title"])];
75
+ })];
60
76
  }),
61
77
  key: "0"
62
78
  } : undefined, _ctx.$slots.loading ? {
@@ -77,7 +93,7 @@ var script = {
77
93
  return [renderSlot(_ctx.$slots, "empty")];
78
94
  }),
79
95
  key: "3"
80
- } : undefined]), 1040 /* FULL_PROPS, DYNAMIC_SLOTS */, ["src", "name", "title", "fix-parent-style"]);
96
+ } : undefined]), 1040 /* FULL_PROPS, DYNAMIC_SLOTS */, ["src", "name", "title", "shell-tab-key", "fix-parent-style"]))]);
81
97
  };
82
98
  }
83
99
  };
@@ -1,6 +1,8 @@
1
1
  import '../_virtual/_rollup-plugin-inject-process-env.js';
2
2
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
- import './ProIframeRouteView.vue.js';
3
+ import script from './ProIframeRouteView.vue.js';
4
+
5
+
4
6
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
7
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
8
  /**
@@ -0,0 +1,15 @@
1
+ import { type DepponProLayoutTabBridge, type DepponProLayoutTabBridgeOpenOptions } from '../pro-layout/pro-layout-tab-bridge';
2
+ export declare const DEPPON_IFRAME_HOST_KEY = "__DEPPON_IFRAME_HOST__";
3
+ export interface DepponIframeHostBridge {
4
+ /** 壳层路由 fullPath(ProLayout 页签 key) */
5
+ shellFullPath: string;
6
+ layoutTabBridge?: DepponProLayoutTabBridge;
7
+ closeTab: (url?: string) => boolean;
8
+ openTab: (location: unknown, options?: DepponProLayoutTabBridgeOpenOptions) => unknown;
9
+ activateTab?: (location: unknown) => unknown;
10
+ }
11
+ /**
12
+ * 在同源 iframe 子页注入宿主桥接,使子页 deppon-router 可关闭/新开壳层页签。
13
+ */
14
+ export declare function installIframeHostBridge(contentWindow: Window, shellFullPath: string, parentWin?: Window): boolean;
15
+ export declare function getIframeHostBridge(win?: Window): DepponIframeHostBridge | null;
@@ -0,0 +1,49 @@
1
+ import '../_virtual/_rollup-plugin-inject-process-env.js';
2
+ import _defineProperty from '@babel/runtime/helpers/defineProperty';
3
+ import { DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY } from '../pro-layout/pro-layout-tab-bridge.js';
4
+
5
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
+ var DEPPON_IFRAME_HOST_KEY = '__DEPPON_IFRAME_HOST__';
8
+ /**
9
+ * 在同源 iframe 子页注入宿主桥接,使子页 deppon-router 可关闭/新开壳层页签。
10
+ */
11
+ function installIframeHostBridge(contentWindow, shellFullPath) {
12
+ var parentWin = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window;
13
+ if (!contentWindow || contentWindow === parentWin) {
14
+ return false;
15
+ }
16
+ try {
17
+ var layoutTabBridge = parentWin[DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY];
18
+ var host = _objectSpread(_objectSpread({
19
+ shellFullPath: shellFullPath
20
+ }, layoutTabBridge ? {
21
+ layoutTabBridge: layoutTabBridge
22
+ } : {}), {}, {
23
+ closeTab: function closeTab(url) {
24
+ if (layoutTabBridge !== null && layoutTabBridge !== void 0 && layoutTabBridge.closeTab) {
25
+ return layoutTabBridge.closeTab(url || shellFullPath);
26
+ }
27
+ return false;
28
+ },
29
+ openTab: function openTab(location, options) {
30
+ if (layoutTabBridge !== null && layoutTabBridge !== void 0 && layoutTabBridge.openTab) {
31
+ return layoutTabBridge.openTab(location, options);
32
+ }
33
+ return false;
34
+ },
35
+ activateTab: function activateTab(location) {
36
+ if (layoutTabBridge !== null && layoutTabBridge !== void 0 && layoutTabBridge.activateTab) {
37
+ return layoutTabBridge.activateTab(location);
38
+ }
39
+ return false;
40
+ }
41
+ });
42
+ contentWindow[DEPPON_IFRAME_HOST_KEY] = host;
43
+ return true;
44
+ } catch (_unused) {
45
+ return false;
46
+ }
47
+ }
48
+
49
+ export { DEPPON_IFRAME_HOST_KEY, installIframeHostBridge };
@@ -21,7 +21,6 @@ export {
21
21
  export { buildIframeRouteLocation } from './buildIframeRouteLocation';
22
22
  export { isInIframeEmbed } from './isInIframeEmbed';
23
23
  export { createIframeRoute } from './createIframeRoute';
24
- export function isInIframeEmbed(): boolean;
25
24
  export type { ProIframeRouteMeta, ProIframeProps, CreateIframeRouteOptions, BuildIframeRouteLocationOptions };
26
25
 
27
26
  export function resolveIframeSrcFromRoute(route: RouteLocationNormalizedLoaded): string;
@@ -7,6 +7,8 @@ export declare const PRO_IFRAME_URL_PARAM_KEYS: readonly ["iframeUrl", "url", "l
7
7
  export declare const PRO_IFRAME_URL_RESERVED_QUERY_KEYS: readonly ["iframeUrl", "url", "link", "src", "title", "iframeTitle"];
8
8
  /** 解码路由上的 url(支持 encodeURIComponent 后的完整地址) */
9
9
  export declare function decodeIframeUrlValue(value: string): string;
10
+ /** 写入路由 query.url 时编码,避免内嵌地址中的 &/? 被 Vue Router 拆成多个 query */
11
+ export declare function encodeIframeUrlForQuery(value: string): string;
10
12
  /** 将 query 对象合并进 URL(覆盖同名 search 参数) */
11
13
  export declare function appendQueryToUrl(url: string, query: Record<string, string>): string;
12
14
  /** 将 meta.iframeUrl 中的 :param / :queryKey 占位替换为路由 params、query */
@@ -62,7 +62,7 @@ function appendQueryToUrl(url, query) {
62
62
  return "".concat(parsed.pathname).concat(parsed.search).concat(parsed.hash);
63
63
  }
64
64
  return parsed.toString();
65
- } catch (_unused2) {
65
+ } catch (_unused3) {
66
66
  var separator = url.includes('?') ? '&' : '?';
67
67
  var qs = Object.entries(query).map(function (_ref3) {
68
68
  var _ref4 = _slicedToArray(_ref3, 2),
@@ -39,6 +39,8 @@ export interface ProIframeRouteMeta {
39
39
  iframeLazy?: boolean;
40
40
  iframeFull?: boolean;
41
41
  iframeFixParentStyle?: boolean;
42
+ /** ProIframeRouteView 是否展示默认 toolbar(刷新、新窗口打开);默认 false,传 true 开启 */
43
+ iframeToolbar?: boolean;
42
44
  iframeProps?: Record<string, unknown>;
43
45
  }
44
46
  export interface ProIframeProps {
@@ -1402,6 +1402,11 @@ body .el-overlay-dialog,
1402
1402
  .pro-layout__sider .pro-layout__menu-group .el-menu.el-menu--vertical .el-sub-menu__title::after {
1403
1403
  display: none !important;
1404
1404
  }
1405
+ .pro-layout__sider .pro-layout__menu .el-menu {
1406
+ /* 较 EP 默认(20+20*level)略收窄,一级约 16px、二级约 30px,兼顾层级与侧栏宽度 */
1407
+ --el-menu-base-level-padding: 16px;
1408
+ --el-menu-level-padding: 14px;
1409
+ }
1405
1410
  .pro-layout__sider .el-menu-item,
1406
1411
  .pro-layout__sider .el-sub-menu__title {
1407
1412
  height: 44px !important;
@@ -1426,7 +1431,8 @@ body .el-overlay-dialog,
1426
1431
  min-height: 40px !important;
1427
1432
  height: 40px !important;
1428
1433
  line-height: 40px !important;
1429
- margin: 2px 8px 2px 12px !important;
1434
+ margin: 2px calc(8px + var(--pro-el-scrollbar-width, 9px)) 2px 10px !important;
1435
+ padding-right: 12px !important;
1430
1436
  border-radius: 8px !important;
1431
1437
  }
1432
1438
  .pro-layout__sider .el-sub-menu.is-active > .el-sub-menu__title {
@@ -2618,6 +2624,14 @@ body .el-overlay-dialog,
2618
2624
  overflow-y: auto;
2619
2625
  overflow-x: hidden;
2620
2626
  }
2627
+ .pro-layout__content--iframe {
2628
+ overflow: hidden !important;
2629
+ }
2630
+ .pro-layout__content--iframe > * {
2631
+ height: 100% !important;
2632
+ min-height: 0 !important;
2633
+ overflow: hidden !important;
2634
+ }
2621
2635
  .pro-layout__footer {
2622
2636
  flex-shrink: 0;
2623
2637
  background-color: var(--el-bg-color, #ffffff) !important;
@@ -3,11 +3,13 @@ import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
3
3
  import _typeof from '@babel/runtime/helpers/typeof';
4
4
  import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
5
5
  import _defineProperty from '@babel/runtime/helpers/defineProperty';
6
- import { useSlots, ref, computed, provide, watch, markRaw, onMounted, onUnmounted, nextTick, openBlock, createBlock, unref, normalizeClass, normalizeStyle, withCtx, createElementVNode, createElementBlock, renderSlot, createCommentVNode, createTextVNode, toDisplayString, createVNode, Fragment, renderList, withModifiers, resolveDynamicComponent, withDirectives, mergeProps, vShow, createSlots } from 'vue';
6
+ import { useSlots, computed, ref, provide, watch, markRaw, onMounted, onUnmounted, nextTick, openBlock, createBlock, unref, normalizeClass, normalizeStyle, withCtx, createElementVNode, createElementBlock, renderSlot, createCommentVNode, createTextVNode, toDisplayString, createVNode, Fragment, renderList, withModifiers, resolveDynamicComponent, withDirectives, mergeProps, vShow, createSlots } from 'vue';
7
7
  import { useRouter, useRoute } from '@deppon/deppon-router';
8
8
  import { ElContainer, ElHeader, ElMenu, ElMenuItem, ElIcon, ElBadge, ElSubMenu, ElInput, ElButton, ElAside, ElScrollbar, ElTooltip, ElMain, ElFooter, ElMessage } from '@deppon/deppon-ui';
9
9
  import { Search, Service, Bell, Close, House, Expand, Fold, ArrowRight, ArrowLeft } from '@deppon/deppon-ui/icons-vue';
10
10
  import { isMobile as _isMobile } from '../utils/other.js';
11
+ import { isIframeRoute } from '../pro-iframe/resolveIframeSrc.js';
12
+ import { DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY, normalizeTabMatchUrl } from './pro-layout-tab-bridge.js';
11
13
  import './ProLayoutColumnsAside.vue.js';
12
14
  import './ProLayoutSettingsFab.vue.js';
13
15
  import './ProLayoutSettingsDrawer.vue.js';
@@ -404,6 +406,13 @@ var script = {
404
406
  var slots = useSlots();
405
407
  var router = useRouter();
406
408
  var route = useRoute();
409
+
410
+ /** 当前内容区是否为 iframe 路由(需占满高度,避免内嵌页 toolbar 被裁切) */
411
+ var isIframeContentRoute = computed(function () {
412
+ var _route$matched;
413
+ var matched = (_route$matched = route.matched) === null || _route$matched === void 0 ? void 0 : _route$matched[route.matched.length - 1];
414
+ return isIframeRoute((matched === null || matched === void 0 ? void 0 : matched.meta) || route.meta);
415
+ });
407
416
  var props = __props;
408
417
  var emit = __emit;
409
418
  var localCollapsed = ref(props.collapsed);
@@ -692,8 +701,105 @@ var script = {
692
701
  visitedTags.value.unshift(homeTag);
693
702
  }
694
703
  };
704
+ /** iframe 路由用 fullPath 区分页签(同 path 不同 url query 须新开页签) */
705
+ var getRouteTagKey = function getRouteTagKey(route) {
706
+ var _route$matched2;
707
+ var meta = route.meta || ((_route$matched2 = route.matched) === null || _route$matched2 === void 0 || (_route$matched2 = _route$matched2[route.matched.length - 1]) === null || _route$matched2 === void 0 ? void 0 : _route$matched2.meta);
708
+ if (isIframeRoute(meta)) {
709
+ return route.fullPath;
710
+ }
711
+ return route.path;
712
+ };
713
+ var getRouteTagKeyFromResolved = function getRouteTagKeyFromResolved(resolved) {
714
+ var _resolved$matched;
715
+ var matched = (_resolved$matched = resolved.matched) === null || _resolved$matched === void 0 ? void 0 : _resolved$matched[resolved.matched.length - 1];
716
+ var meta = (matched === null || matched === void 0 ? void 0 : matched.meta) || resolved.meta;
717
+ if (isIframeRoute(meta)) {
718
+ return resolved.fullPath;
719
+ }
720
+ return resolved.path;
721
+ };
722
+ var getRouteTitleFromResolved = function getRouteTitleFromResolved(resolved, optionsTitle) {
723
+ var _resolved$query, _resolved$query2, _resolved$matched2;
724
+ if (optionsTitle) return optionsTitle;
725
+ var qTitle = ((_resolved$query = resolved.query) === null || _resolved$query === void 0 ? void 0 : _resolved$query.title) || ((_resolved$query2 = resolved.query) === null || _resolved$query2 === void 0 ? void 0 : _resolved$query2.iframeTitle);
726
+ var q = Array.isArray(qTitle) ? qTitle[0] : qTitle;
727
+ if (q) return String(q);
728
+ var matched = (_resolved$matched2 = resolved.matched) === null || _resolved$matched2 === void 0 ? void 0 : _resolved$matched2[resolved.matched.length - 1];
729
+ var meta = (matched === null || matched === void 0 ? void 0 : matched.meta) || resolved.meta;
730
+ if (meta !== null && meta !== void 0 && meta.title) return meta.title;
731
+ var menuTitle = _findMenuTitle(resolved.path);
732
+ if (menuTitle) return menuTitle;
733
+ return resolved.name || resolved.path;
734
+ };
735
+ /** 重复导航时 replace,确保可切换到已打开的页签 */
736
+ var pushRouteLocation = function pushRouteLocation(target) {
737
+ var rawPush = router.__depponOriginalPush || function (loc) {
738
+ return router.push(loc);
739
+ };
740
+ return rawPush(target)["catch"](function (err) {
741
+ if ((err === null || err === void 0 ? void 0 : err.name) === 'NavigationDuplicated') {
742
+ var rawReplace = router.__depponOriginalReplace || function (loc) {
743
+ return router.replace(loc);
744
+ };
745
+ return rawReplace(target);
746
+ }
747
+ throw err;
748
+ });
749
+ };
750
+ var findTagByLocation = function findTagByLocation(location) {
751
+ if (!location) return null;
752
+ try {
753
+ var resolved = router.resolve(location);
754
+ var key = getRouteTagKeyFromResolved(resolved);
755
+ return visitedTags.value.find(function (t) {
756
+ return t.path === key;
757
+ }) || null;
758
+ } catch (_unused) {
759
+ return null;
760
+ }
761
+ };
762
+ var openLayoutTab = function openLayoutTab(location, options) {
763
+ if (!location) return Promise.resolve();
764
+ var target = location;
765
+ if (_typeof(location) === 'object' && options !== null && options !== void 0 && options.title) {
766
+ var q = _objectSpread({}, location.query || {});
767
+ if (!q.title) q.title = options.title;
768
+ target = _objectSpread(_objectSpread({}, location), {}, {
769
+ query: q
770
+ });
771
+ }
772
+ var resolved = router.resolve(target);
773
+ var key = getRouteTagKeyFromResolved(resolved);
774
+ var title = getRouteTitleFromResolved(resolved, options === null || options === void 0 ? void 0 : options.title);
775
+ var existingTag = visitedTags.value.find(function (tag) {
776
+ return tag.path === key;
777
+ });
778
+ var dest = resolved.fullPath || resolved.path;
779
+ if (existingTag) {
780
+ existingTag.title = title;
781
+ existingTag.fullPath = dest;
782
+ currentPath.value = key;
783
+ return pushRouteLocation(dest);
784
+ }
785
+ return pushRouteLocation(target);
786
+ };
787
+ var activateLayoutTab = function activateLayoutTab(location) {
788
+ var existing = findTagByLocation(location);
789
+ if (!existing) return Promise.resolve(false);
790
+ currentPath.value = existing.path;
791
+ return pushRouteLocation(existing.fullPath || existing.path).then(function () {
792
+ return true;
793
+ });
794
+ };
695
795
  var getRouteTitle = function getRouteTitle(route) {
696
796
  var _route$meta;
797
+ if (isIframeRoute(route.meta)) {
798
+ var _route$query, _route$query2;
799
+ var fromQuery = ((_route$query = route.query) === null || _route$query === void 0 ? void 0 : _route$query.title) || ((_route$query2 = route.query) === null || _route$query2 === void 0 ? void 0 : _route$query2.iframeTitle);
800
+ var q = Array.isArray(fromQuery) ? fromQuery[0] : fromQuery;
801
+ if (q) return String(q);
802
+ }
697
803
  if ((_route$meta = route.meta) !== null && _route$meta !== void 0 && _route$meta.title) {
698
804
  return route.meta.title;
699
805
  }
@@ -704,19 +810,22 @@ var script = {
704
810
  return route.name || route.path;
705
811
  };
706
812
  var addTag = function addTag(route) {
707
- var path = route.path;
813
+ var key = getRouteTagKey(route);
708
814
  var title = getRouteTitle(route);
709
815
  var existingTag = visitedTags.value.find(function (tag) {
710
- return tag.path === path;
816
+ return tag.path === key;
711
817
  });
712
- if (!existingTag) {
818
+ if (existingTag) {
819
+ existingTag.title = title;
820
+ existingTag.fullPath = route.fullPath;
821
+ } else {
713
822
  visitedTags.value.push({
714
- path: path,
823
+ path: key,
715
824
  title: title,
716
825
  fullPath: route.fullPath
717
826
  });
718
827
  }
719
- currentPath.value = path;
828
+ currentPath.value = key;
720
829
  };
721
830
  var removeTag = function removeTag(tag) {
722
831
  if (tag.path === tagsViewHomePath.value) {
@@ -737,9 +846,38 @@ var script = {
737
846
  }
738
847
  }
739
848
  };
849
+ var findTagByCloseUrl = function findTagByCloseUrl(url) {
850
+ if (!url) {
851
+ return visitedTags.value.find(function (t) {
852
+ return t.path === getRouteTagKey(route);
853
+ });
854
+ }
855
+ var normalized = normalizeTabMatchUrl(url);
856
+ var href = typeof window !== 'undefined' ? normalizeTabMatchUrl(window.location.href) : '';
857
+ return visitedTags.value.find(function (tag) {
858
+ var tagKey = tag.path;
859
+ var tagFull = tag.fullPath ? normalizeTabMatchUrl(tag.fullPath) : '';
860
+ if (tagKey === url || tagKey === normalized) return true;
861
+ if (tagFull && (tagFull === normalized || tagFull === url)) return true;
862
+ if (href && (tagFull === href || tagKey === href)) return true;
863
+ return false;
864
+ });
865
+ };
866
+ var closeLayoutTab = function closeLayoutTab(url) {
867
+ if (!showTagsViewResolved.value) {
868
+ return false;
869
+ }
870
+ var tag = findTagByCloseUrl(url);
871
+ if (tag) {
872
+ removeTag(tag);
873
+ return true;
874
+ }
875
+ return false;
876
+ };
740
877
  var handleTagClick = function handleTagClick(tag) {
741
878
  if (tag.path !== currentPath.value) {
742
- router.push(tag.fullPath || tag.path);
879
+ currentPath.value = tag.path;
880
+ pushRouteLocation(tag.fullPath || tag.path);
743
881
  }
744
882
  };
745
883
  var handleTagMenuSelect = function handleTagMenuSelect(index) {
@@ -758,15 +896,29 @@ var script = {
758
896
  emit('tag-close', tag);
759
897
  };
760
898
  watch(function () {
761
- return route.path;
762
- }, function (newPath) {
763
- if (showTagsViewResolved.value && newPath) {
899
+ return getRouteTagKey(route);
900
+ }, function (newKey) {
901
+ if (showTagsViewResolved.value && newKey) {
764
902
  addTag(route);
765
903
  ensureAffixHomeTag();
766
904
  }
767
905
  }, {
768
906
  immediate: true
769
907
  });
908
+ var layoutTabBridge = {
909
+ isTagsViewEnabled: function isTagsViewEnabled() {
910
+ return showTagsViewResolved.value;
911
+ },
912
+ openTab: function openTab(location, options) {
913
+ return openLayoutTab(location, options);
914
+ },
915
+ activateTab: function activateTab(location) {
916
+ return activateLayoutTab(location);
917
+ },
918
+ closeTab: function closeTab(url) {
919
+ return closeLayoutTab(url);
920
+ }
921
+ };
770
922
  var SearchIcon = markRaw(Search);
771
923
  var PhoneIcon = markRaw(Service);
772
924
  var BellIcon = markRaw(Bell);
@@ -895,6 +1047,9 @@ var script = {
895
1047
  nextTick(checkAllMenuTitleOverflow);
896
1048
  };
897
1049
  onMounted(function () {
1050
+ if (typeof window !== 'undefined') {
1051
+ window[DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY] = layoutTabBridge;
1052
+ }
898
1053
  if (themeConfigState.value.isCollapse !== undefined) {
899
1054
  collapsed.value = themeConfigState.value.isCollapse;
900
1055
  }
@@ -919,6 +1074,9 @@ var script = {
919
1074
  }
920
1075
  });
921
1076
  onUnmounted(function () {
1077
+ if (typeof window !== 'undefined' && window[DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY] === layoutTabBridge) {
1078
+ delete window[DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY];
1079
+ }
922
1080
  window.removeEventListener('resize', handleMenuTitleResize);
923
1081
  if (props.responsive) {
924
1082
  window.removeEventListener('resize', checkMobile);
@@ -1847,13 +2005,15 @@ var script = {
1847
2005
  }),
1848
2006
  _: 1 /* STABLE */
1849
2007
  }, 8 /* PROPS */, ["default-active"]))], 4 /* STYLE */)) : createCommentVNode("v-if", true), createVNode(unref(ElMain), {
1850
- "class": "pro-layout__content"
2008
+ "class": normalizeClass(["pro-layout__content", {
2009
+ 'pro-layout__content--iframe': isIframeContentRoute.value
2010
+ }])
1851
2011
  }, {
1852
2012
  "default": withCtx(function () {
1853
2013
  return [renderSlot(_ctx.$slots, "default")];
1854
2014
  }),
1855
2015
  _: 3 /* FORWARDED */
1856
- }), __props.showFooter ? (openBlock(), createBlock(unref(ElFooter), {
2016
+ }, 8 /* PROPS */, ["class"]), __props.showFooter ? (openBlock(), createBlock(unref(ElFooter), {
1857
2017
  key: 1,
1858
2018
  height: __props.footerHeight,
1859
2019
  "class": "pro-layout__footer"
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ProLayout 页签桥接(对齐 UAP/Ext 的 top.viewTab / top.closeTab)
3
+ * 供 @deppon/deppon-router 在壳层页签模式下打开/关闭页签,避免与 deppon-template 循环依赖。
4
+ */
5
+ export declare const DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY = "__DEPPON_PRO_LAYOUT_TAB_BRIDGE__";
6
+ export interface DepponProLayoutTabBridgeOpenOptions {
7
+ title?: string;
8
+ }
9
+ export interface DepponProLayoutTabBridge {
10
+ /** 是否已启用页签栏 */
11
+ isTagsViewEnabled: () => boolean;
12
+ /** 打开/激活页签(已存在则切换并 router.push,对齐 Ext viewTab 再次打开) */
13
+ openTab: (location: unknown, options?: DepponProLayoutTabBridgeOpenOptions) => Promise<unknown> | unknown;
14
+ /** 仅激活已有页签(按 path / fullPath 匹配) */
15
+ activateTab?: (location: unknown) => Promise<unknown> | unknown;
16
+ /** 按 shell fullPath / href / path 关闭页签 */
17
+ closeTab: (url?: string) => boolean;
18
+ }
19
+ declare global {
20
+ interface Window {
21
+ [DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY]?: DepponProLayoutTabBridge;
22
+ __DEPPON_IFRAME_HOST__?: import('../pro-iframe/iframeHostBridge').DepponIframeHostBridge;
23
+ }
24
+ }
25
+ export declare function getDepponProLayoutTabBridge(win?: Window): DepponProLayoutTabBridge | null;
26
+ export declare function normalizeTabMatchUrl(url: string, baseOrigin?: string): string;
@@ -0,0 +1,25 @@
1
+ import '../_virtual/_rollup-plugin-inject-process-env.js';
2
+
3
+ /**
4
+ * ProLayout 页签桥接(对齐 UAP/Ext 的 top.viewTab / top.closeTab)
5
+ * 供 @deppon/deppon-router 在壳层页签模式下打开/关闭页签,避免与 deppon-template 循环依赖。
6
+ */
7
+
8
+ var DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY = '__DEPPON_PRO_LAYOUT_TAB_BRIDGE__';
9
+ function normalizeTabMatchUrl(url, baseOrigin) {
10
+ if (!url) return '';
11
+ var origin = baseOrigin || (typeof window !== 'undefined' ? window.location.origin : '');
12
+ try {
13
+ if (url.startsWith('http://') || url.startsWith('https://')) {
14
+ return new URL(url).href;
15
+ }
16
+ if (url.startsWith('#')) {
17
+ return new URL(url, "".concat(origin, "/")).href;
18
+ }
19
+ return new URL(url, "".concat(origin, "/")).href;
20
+ } catch (_unused2) {
21
+ return url;
22
+ }
23
+ }
24
+
25
+ export { DEPPON_PRO_LAYOUT_TAB_BRIDGE_KEY, normalizeTabMatchUrl };
package/package.json CHANGED
@@ -1,9 +1,17 @@
1
1
  {
2
2
  "name": "@deppon/deppon-template",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "main": "es/index.js",
5
5
  "module": "es/index.js",
6
6
  "typings": "es/index.d.ts",
7
+ "types": "es/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./es/index.d.ts",
11
+ "import": "./es/index.js",
12
+ "default": "./es/index.js"
13
+ }
14
+ },
7
15
  "sideEffects": [
8
16
  "*.css",
9
17
  "**/*.css",
@@ -43,11 +51,11 @@
43
51
  "less": "^4.2.0"
44
52
  },
45
53
  "dependencies": {
46
- "@deppon/deppon-assets": "2.5.4",
47
- "@deppon/deppon-request": "2.5.4",
48
- "@deppon/deppon-router": "2.5.4",
49
- "@deppon/deppon-ui": "2.5.4",
50
- "@deppon/deppon-utils": "2.5.4",
54
+ "@deppon/deppon-assets": "2.5.6",
55
+ "@deppon/deppon-request": "2.5.6",
56
+ "@deppon/deppon-router": "2.5.6",
57
+ "@deppon/deppon-ui": "2.5.6",
58
+ "@deppon/deppon-utils": "2.5.6",
51
59
  "dayjs": "^1.11.10",
52
60
  "lodash-es": "^4.17.21",
53
61
  "mitt": "^3.0.1"