@lemon-fe/kits 1.0.0-177 → 1.0.0-178

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.
@@ -1367,6 +1367,7 @@ var DataGrid = /*#__PURE__*/function (_Component) {
1367
1367
 
1368
1368
  if (showSearch) {
1369
1369
  footer.push( /*#__PURE__*/React.createElement(Search, _extends({
1370
+ key: "search",
1370
1371
  ref: this.searchRef
1371
1372
  }, _typeof(showSearch) === 'object' ? showSearch : {})));
1372
1373
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 校验函数
3
+ * @param block 返回true或者string 会阻止页面被关闭;
4
+ * @returns string 为提示信息,一般情况不需要
5
+ */
6
+ export default function useHistoryBlock(block: () => string | boolean): {
7
+ clear(): void;
8
+ };
@@ -0,0 +1,30 @@
1
+ import { useLastestRef } from '@lemon-fe/hooks';
2
+ import { useContext, useEffect, useRef } from 'react';
3
+ import { useLocation } from 'react-router';
4
+ import { RouteTabContext } from "../../layouts/components/RouteTab";
5
+ /**
6
+ * 校验函数
7
+ * @param block 返回true或者string 会阻止页面被关闭;
8
+ * @returns string 为提示信息,一般情况不需要
9
+ */
10
+
11
+ export default function useHistoryBlock(block) {
12
+ var tabCtx = useContext(RouteTabContext);
13
+ var blockRef = useLastestRef(block);
14
+ var pathname = useLocation().pathname;
15
+ var clearRef = useRef(function () {});
16
+ useEffect(function () {
17
+ clearRef.current = tabCtx.instance.registerCloseBlocker({
18
+ pathname: "".concat(tabCtx.routerBase).concat(pathname),
19
+ block: function block() {
20
+ return blockRef.current();
21
+ }
22
+ });
23
+ return clearRef.current;
24
+ }, []);
25
+ return {
26
+ clear: function clear() {
27
+ clearRef.current();
28
+ }
29
+ };
30
+ }
package/es/index.d.ts CHANGED
@@ -44,9 +44,11 @@ export { default as GreyPanel } from './components/GreyPanel';
44
44
  export { default as Alert } from './components/Alert';
45
45
  export { default as InputNumber } from './components/InputNumber';
46
46
  export { default as InputCompact } from './components/InputCompact';
47
+ export { default as SelectPanel } from './components/SelectPanel';
47
48
  export { default as BasicLayout } from './layouts/BasicLayout';
48
49
  export { default as BlankLayout } from './layouts/BlankLayout';
49
50
  export { default as MicroLayout } from './layouts/MicroLayout';
50
51
  export { default as Breadcrumb } from './layouts/Breadcrumb';
51
52
  export { default as useBatchOperator } from './hooks/useBatchOperator';
52
- export { default as SelectPanel } from './components/SelectPanel';
53
+ export { default as useHistoryBlock } from './hooks/useHistoryBlock';
54
+ export { TabInstance } from './layouts/TabInstance';
package/es/index.js CHANGED
@@ -36,9 +36,11 @@ export { default as GreyPanel } from "./components/GreyPanel";
36
36
  export { default as Alert } from "./components/Alert";
37
37
  export { default as InputNumber } from "./components/InputNumber";
38
38
  export { default as InputCompact } from "./components/InputCompact";
39
+ export { default as SelectPanel } from "./components/SelectPanel";
39
40
  export { default as BasicLayout } from "./layouts/BasicLayout";
40
41
  export { default as BlankLayout } from "./layouts/BlankLayout";
41
42
  export { default as MicroLayout } from "./layouts/MicroLayout";
42
43
  export { default as Breadcrumb } from "./layouts/Breadcrumb";
43
44
  export { default as useBatchOperator } from "./hooks/useBatchOperator";
44
- export { default as SelectPanel } from "./components/SelectPanel";
45
+ export { default as useHistoryBlock } from "./hooks/useHistoryBlock";
46
+ export { TabInstance } from "./layouts/TabInstance";
@@ -4,11 +4,29 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
4
4
 
5
5
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
6
 
7
- import React, { memo } from 'react';
7
+ import { useLastestRef } from '@lemon-fe/hooks';
8
+ import React, { memo, useEffect } from 'react';
8
9
  import { useMemo } from 'react';
9
10
  import { matchPath, useHistory } from 'react-router-dom';
10
11
  import RouteTab from "../components/RouteTab";
11
12
 
13
+ function isSubPath(path, subPath) {
14
+ var pathArr = path.split('/');
15
+ var subPathArr = subPath.split('/');
16
+
17
+ if (path.length > subPath.length) {
18
+ return false;
19
+ }
20
+
21
+ for (var i = 0; i < pathArr.length; i++) {
22
+ if (subPathArr[i] !== pathArr[i]) {
23
+ return false;
24
+ }
25
+ }
26
+
27
+ return true;
28
+ }
29
+
12
30
  function MicroLayout(props) {
13
31
  var _tabs$active;
14
32
 
@@ -31,7 +49,7 @@ function MicroLayout(props) {
31
49
  var key = (_tabs$active = tabs[active]) === null || _tabs$active === void 0 ? void 0 : _tabs$active.rootPath;
32
50
  var routeTabs = useMemo(function () {
33
51
  return tabs.filter(function (tab) {
34
- return new RegExp("".concat(basename, "\\b")).test(tab.rootPath);
52
+ return isSubPath(basename, tab.rootPath);
35
53
  }).map(function (item) {
36
54
  var tab = _objectSpread(_objectSpread({}, item), {}, {
37
55
  location: _objectSpread(_objectSpread({}, item.location), {}, {
@@ -81,6 +99,32 @@ function MicroLayout(props) {
81
99
  return tab;
82
100
  });
83
101
  }, [tabs, routes]);
102
+ var routeTabsRef = useLastestRef(routeTabs);
103
+ useEffect(function () {
104
+ history.block(function (loc, action) {
105
+ if (action === 'POP') {
106
+ return;
107
+ }
108
+
109
+ var pathname = "".concat(basename).concat(loc.pathname);
110
+ var target = routeTabsRef.current.find(function (tab) {
111
+ return isSubPath(tab.rootPath, pathname);
112
+ });
113
+
114
+ if (target === undefined || pathname === target.location.pathname) {
115
+ return;
116
+ }
117
+
118
+ if (target.instance.block({
119
+ title: target.title,
120
+ onOk: function onOk() {
121
+ history.push(loc);
122
+ }
123
+ })) {
124
+ return false;
125
+ }
126
+ });
127
+ }, []);
84
128
  return /*#__PURE__*/React.createElement(React.Fragment, null, routeTabs.map(function (tab, index) {
85
129
  var route = tab.route;
86
130
  return /*#__PURE__*/React.createElement("div", {
@@ -91,13 +135,15 @@ function MicroLayout(props) {
91
135
  height: '100%'
92
136
  }
93
137
  }, route !== null && tab.match !== null && /*#__PURE__*/React.createElement(RouteTab, {
138
+ routerBase: basename,
94
139
  authorities: auth,
95
140
  routes: routes,
96
141
  index: index,
97
142
  history: history,
98
143
  route: route,
99
144
  location: tab.location,
100
- match: tab.match
145
+ match: tab.match,
146
+ instance: tab.instance
101
147
  }));
102
148
  }));
103
149
  }
@@ -1,5 +1,6 @@
1
1
  import type { ReactText } from 'react';
2
2
  import type { IRoute, Location } from '../BasicLayout/typings';
3
+ import type { TabInstance } from '../TabInstance';
3
4
 
4
5
  export interface MicroLayoutProps {
5
6
  /**
@@ -17,6 +18,7 @@ export interface MicroLayoutProps {
17
18
  title: string;
18
19
  rootPath: string;
19
20
  location: Location;
21
+ instance: TabInstance;
20
22
  }[];
21
23
  /**
22
24
  * @description 当前active tab
@@ -0,0 +1,31 @@
1
+ import type { Location } from './typings';
2
+ declare type CloseBlocker = {
3
+ pathname: string;
4
+ block: () => string | boolean;
5
+ };
6
+ /**
7
+ * 为了简化,只会阻止最后一个且当前路由下的history blocker;
8
+ */
9
+ export declare class TabInstance {
10
+ private closeBlockers;
11
+ private rootPath;
12
+ private location;
13
+ constructor(rootPath: string, location: Location);
14
+ update(rootPath: string | undefined, location: Location | undefined): void;
15
+ registerCloseBlocker(blocker: CloseBlocker): () => void;
16
+ private shouldNotBlock;
17
+ /**
18
+ * 用于路由跳转
19
+ * @param modalParams
20
+ * @returns
21
+ */
22
+ block(modalParams: {
23
+ title: string;
24
+ onOk: () => void;
25
+ }): boolean;
26
+ /**
27
+ * @returns 用于关闭tab
28
+ */
29
+ shouldBlock(): string | false;
30
+ }
31
+ export {};
@@ -0,0 +1,115 @@
1
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2
+
3
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
4
+
5
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
6
+
7
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+
9
+ import { Modal } from 'antd';
10
+
11
+ /**
12
+ * 为了简化,只会阻止最后一个且当前路由下的history blocker;
13
+ */
14
+ export var TabInstance = /*#__PURE__*/function () {
15
+ function TabInstance(rootPath, location) {
16
+ _classCallCheck(this, TabInstance);
17
+
18
+ _defineProperty(this, "closeBlockers", []);
19
+
20
+ _defineProperty(this, "rootPath", void 0);
21
+
22
+ _defineProperty(this, "location", void 0);
23
+
24
+ _defineProperty(this, "shouldNotBlock", '');
25
+
26
+ this.rootPath = rootPath;
27
+ this.location = location;
28
+ }
29
+
30
+ _createClass(TabInstance, [{
31
+ key: "update",
32
+ value: function update(rootPath, location) {
33
+ if (rootPath) {
34
+ this.rootPath = rootPath;
35
+ }
36
+
37
+ if (location) {
38
+ this.location = location;
39
+ }
40
+ }
41
+ }, {
42
+ key: "registerCloseBlocker",
43
+ value: function registerCloseBlocker(blocker) {
44
+ var _this = this;
45
+
46
+ this.closeBlockers.push(blocker);
47
+ return function () {
48
+ var index = _this.closeBlockers.findIndex(function (item) {
49
+ return item === blocker;
50
+ });
51
+
52
+ _this.closeBlockers.splice(index, 1);
53
+ };
54
+ }
55
+ }, {
56
+ key: "block",
57
+ value:
58
+ /**
59
+ * 用于路由跳转
60
+ * @param modalParams
61
+ * @returns
62
+ */
63
+ function block(modalParams) {
64
+ var _this2 = this;
65
+
66
+ var shouldNotBlock = this.shouldNotBlock;
67
+ this.shouldNotBlock = '';
68
+
69
+ if (this.closeBlockers.length > 0) {
70
+ var last = this.closeBlockers[this.closeBlockers.length - 1];
71
+
72
+ if (last.pathname === this.location.pathname && last.pathname !== shouldNotBlock) {
73
+ var shouldBlock = last.block();
74
+
75
+ if (shouldBlock) {
76
+ Modal.confirm({
77
+ title: modalParams.title,
78
+ content: typeof shouldBlock === 'string' ? shouldBlock : "\u9875\u9762\u672A\u4FDD\u5B58\uFF0C\u786E\u8BA4\u79BB\u5F00\uFF1F",
79
+ onOk: function onOk() {
80
+ _this2.shouldNotBlock = last.pathname;
81
+ modalParams.onOk();
82
+ }
83
+ });
84
+ return true;
85
+ }
86
+ }
87
+ }
88
+
89
+ return false;
90
+ }
91
+ /**
92
+ * @returns 用于关闭tab
93
+ */
94
+
95
+ }, {
96
+ key: "shouldBlock",
97
+ value: function shouldBlock() {
98
+ if (this.closeBlockers.length > 0) {
99
+ var last = this.closeBlockers[this.closeBlockers.length - 1];
100
+
101
+ if (last.pathname === this.location.pathname) {
102
+ var result = last.block();
103
+
104
+ if (result) {
105
+ return typeof result === 'string' ? result : '页面未保存,确认离开?';
106
+ }
107
+ }
108
+ }
109
+
110
+ return false;
111
+ }
112
+ }]);
113
+
114
+ return TabInstance;
115
+ }();
@@ -1,20 +1,24 @@
1
1
  import React from 'react';
2
- import type { ReactText } from 'react';
3
2
  import { type match } from 'react-router';
3
+ import type { TabInstance } from '../TabInstance';
4
4
  import type { IRoute, Location } from '../typings';
5
5
  interface Props {
6
+ routerBase: string;
6
7
  route: IRoute;
7
8
  routes: IRoute[];
8
9
  index: number;
9
10
  location: Location;
10
11
  match: match;
11
12
  history: any;
12
- authorities?: Set<ReactText>;
13
- pathAuthorities?: Map<string, ReactText | ReactText[]>;
13
+ authorities?: Set<string | number>;
14
+ pathAuthorities?: Map<string, string | number | (string | number)[]>;
15
+ instance: TabInstance;
14
16
  }
15
17
  export declare const RouteTabContext: React.Context<{
16
18
  route: IRoute;
17
19
  match: match;
20
+ routerBase: string;
21
+ instance: TabInstance;
18
22
  }>;
19
23
  declare const _default: React.NamedExoticComponent<Props>;
20
24
  export default _default;
@@ -10,11 +10,15 @@ export default /*#__PURE__*/memo(function RouteTab(props) {
10
10
  history = props.history,
11
11
  routes = props.routes,
12
12
  authorities = props.authorities,
13
- pathAuthorities = props.pathAuthorities;
13
+ pathAuthorities = props.pathAuthorities,
14
+ instance = props.instance,
15
+ routerBase = props.routerBase;
14
16
  var ctx = useMemo(function () {
15
17
  return {
16
18
  match: match,
17
- route: route
19
+ route: route,
20
+ instance: instance,
21
+ routerBase: routerBase
18
22
  };
19
23
  }, [route]);
20
24
  return /*#__PURE__*/React.createElement(RouterContext.Provider, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lemon-fe/kits",
3
- "version": "1.0.0-177",
3
+ "version": "1.0.0-178",
4
4
  "scripts": {
5
5
  "start": "dumi dev",
6
6
  "docs:build": "dumi build",