@jiangood/open-admin 2.5.5 → 2.5.7

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.
Files changed (112) hide show
  1. package/config/common-plugin.js +2 -2
  2. package/package.json +3 -2
  3. package/src/.umi-production/appData.json +91 -90
  4. package/src/.umi-production/core/route.tsx +6 -6
  5. package/src/.umi-production/umi.ts +1 -1
  6. package/src/framework/GlobalData.d.ts +8 -0
  7. package/src/framework/GlobalData.js +33 -0
  8. package/src/framework/{components/system → biz}/HasPerm.tsx +1 -1
  9. package/src/framework/{components/OrgTree/index.tsx → biz/OrgTree.tsx} +12 -2
  10. package/src/framework/{components/system/ButtonList.tsx → biz/PermActions.tsx} +6 -5
  11. package/src/framework/{components/RoleTree/index.tsx → biz/RoleTree.tsx} +13 -3
  12. package/src/framework/{components/system → biz}/index.tsx +4 -2
  13. package/src/framework/components/ContextMenu/index.tsx +12 -4
  14. package/src/framework/components/DownloadModal/index.tsx +332 -0
  15. package/src/framework/components/ErrorBoundary/index.tsx +18 -0
  16. package/src/framework/components/NamedIcon/{index.jsx → index.tsx} +8 -3
  17. package/src/framework/components/Page/index.tsx +2 -2
  18. package/src/framework/components/ProTable/index.tsx +3 -10
  19. package/src/framework/components/index.ts +2 -6
  20. package/src/framework/fields/BaseRemoteSelect/index.tsx +2 -3
  21. package/src/framework/fields/FieldBoolean/index.tsx +3 -4
  22. package/src/framework/fields/FieldDate/index.tsx +0 -21
  23. package/src/framework/fields/FieldEditor/index.tsx +35 -44
  24. package/src/framework/fields/FieldNumberRange/index.tsx +2 -2
  25. package/src/framework/fields/FieldRemoteTree/index.tsx +1 -1
  26. package/src/framework/fields/FieldTable/index.tsx +24 -27
  27. package/src/framework/fields/FieldUploadFile/index.tsx +10 -3
  28. package/src/framework/fields/index.ts +1 -3
  29. package/src/framework/index.ts +2 -0
  30. package/src/framework/utils/ArrayUtils.d.ts +6 -0
  31. package/src/framework/utils/ArrayUtils.js +30 -0
  32. package/src/framework/utils/DateUtils.d.ts +20 -0
  33. package/src/framework/utils/DateUtils.js +81 -0
  34. package/src/framework/utils/DeviceUtils.d.ts +3 -0
  35. package/src/framework/utils/DeviceUtils.js +10 -0
  36. package/src/framework/utils/EventBus.d.ts +6 -0
  37. package/src/framework/utils/EventBus.js +51 -0
  38. package/src/framework/utils/MessageUtils.d.ts +10 -0
  39. package/src/framework/utils/MessageUtils.js +43 -0
  40. package/src/framework/utils/ObjectUtils.d.ts +14 -0
  41. package/src/framework/utils/ObjectUtils.js +12 -0
  42. package/src/framework/utils/StorageUtils.d.ts +4 -0
  43. package/src/framework/utils/{StorageUtils.ts → StorageUtils.js} +7 -11
  44. package/src/framework/utils/StringUtils.d.ts +17 -0
  45. package/src/framework/utils/StringUtils.js +107 -0
  46. package/src/framework/utils/TreeUtils.d.ts +13 -0
  47. package/src/framework/utils/TreeUtils.js +64 -0
  48. package/src/framework/utils/UrlUtils.d.ts +6 -0
  49. package/src/framework/utils/UrlUtils.js +71 -0
  50. package/src/framework/utils/index.ts +1 -5
  51. package/src/framework/utils/system/DictUtils.d.ts +20 -0
  52. package/src/framework/utils/system/DictUtils.js +31 -0
  53. package/src/framework/utils/system/FormRegistry.d.ts +8 -0
  54. package/src/framework/utils/system/FormRegistry.js +31 -0
  55. package/src/framework/utils/system/HttpUtils.d.ts +14 -0
  56. package/src/framework/utils/system/HttpUtils.js +87 -0
  57. package/src/framework/utils/system/PageUtils.d.ts +14 -0
  58. package/src/framework/utils/system/PageUtils.js +59 -0
  59. package/src/framework/utils/system/PermUtils.d.ts +5 -0
  60. package/src/framework/utils/system/PermUtils.js +27 -0
  61. package/src/framework/utils/system/ThemeUtils.d.ts +6 -0
  62. package/src/framework/utils/system/{ThemeUtils.ts → ThemeUtils.js} +19 -19
  63. package/src/framework/utils/system/index.ts +1 -2
  64. package/src/framework/views/ViewFile/index.tsx +3 -3
  65. package/src/framework/views/ViewImage/index.tsx +3 -3
  66. package/src/framework/views/{ViewBooleanEnableDisable → ViewSwitch}/index.tsx +1 -1
  67. package/src/framework/views/index.ts +3 -4
  68. package/src/layouts/admin/HeaderRight.jsx +32 -47
  69. package/src/layouts/admin/index.jsx +5 -29
  70. package/src/layouts/index.jsx +29 -19
  71. package/src/pages/about.jsx +0 -1
  72. package/src/pages/{userCenter/ChangePassword.jsx → account/changePassword.jsx} +1 -2
  73. package/src/pages/{userCenter → account}/index.jsx +2 -6
  74. package/src/pages/forceUpdatePwd.jsx +89 -0
  75. package/src/pages/login.jsx +5 -5
  76. package/src/pages/system/dict/index.jsx +6 -6
  77. package/src/pages/system/file/index.jsx +4 -4
  78. package/src/pages/system/job/index.jsx +2 -2
  79. package/src/pages/system/org/index.jsx +2 -2
  80. package/src/pages/system/role/index.jsx +4 -4
  81. package/src/pages/system/role/{perm.jsx → rolePerm.jsx} +2 -2
  82. package/src/pages/system/user/index.jsx +4 -4
  83. package/src/framework/components/DownloadFileButton/index.tsx +0 -33
  84. package/src/framework/components/NamedIcon/index.d.ts +0 -7
  85. package/src/framework/components/ProTable/utils/index.ts +0 -62
  86. package/src/framework/fields/FieldRemoteSelectMultipleInline/index.tsx +0 -33
  87. package/src/framework/fields/FieldRemoteTreeSelectMultiple/index.tsx +0 -43
  88. package/src/framework/utils/ArrayUtils.ts +0 -186
  89. package/src/framework/utils/ColorsUtils.ts +0 -378
  90. package/src/framework/utils/DateUtils.ts +0 -187
  91. package/src/framework/utils/DeviceUtils.ts +0 -46
  92. package/src/framework/utils/DomUtils.ts +0 -50
  93. package/src/framework/utils/EventBusUtils.ts +0 -143
  94. package/src/framework/utils/Logger.ts +0 -40
  95. package/src/framework/utils/MessageUtils.tsx +0 -90
  96. package/src/framework/utils/ObjectUtils.ts +0 -118
  97. package/src/framework/utils/StringUtils.ts +0 -436
  98. package/src/framework/utils/TreeUtils.ts +0 -251
  99. package/src/framework/utils/UrlUtils.ts +0 -152
  100. package/src/framework/utils/UuidUtils.ts +0 -88
  101. package/src/framework/utils/ValidateUtils.ts +0 -28
  102. package/src/framework/utils/system/DictUtils.ts +0 -96
  103. package/src/framework/utils/system/FormRegistryUtils.ts +0 -76
  104. package/src/framework/utils/system/HttpUtils.ts +0 -251
  105. package/src/framework/utils/system/PageUtils.ts +0 -163
  106. package/src/framework/utils/system/PermUtils.ts +0 -79
  107. package/src/framework/utils/system/SysUtils.ts +0 -105
  108. package/src/framework/views/ViewProcessInstanceProgress/index.tsx +0 -98
  109. package/src/framework/views/ViewProcessInstanceProgressButton/index.tsx +0 -23
  110. package/src/pages/userCenter/message.jsx +0 -105
  111. /package/src/framework/{components → views}/ViewRange/index.tsx +0 -0
  112. /package/src/pages/system/user/{UserPerm.jsx → userPerm.jsx} +0 -0
@@ -0,0 +1,6 @@
1
+ declare const OPEN_ADMIN_THEME: Record<string, string> | undefined;
2
+
3
+ export class ThemeUtils {
4
+ static readonly theme: Record<string, string>;
5
+ static getColor(key: string): string | undefined;
6
+ }
@@ -1,9 +1,5 @@
1
- import {ColorsUtils} from '../ColorsUtils';
2
-
3
- declare const OPEN_ADMIN_THEME: Record<string, string> | undefined;
4
-
5
1
  export class ThemeUtils {
6
- private static readonly defaultTheme: Record<string, string> = {
2
+ static defaultTheme = {
7
3
  "primary-color": "#1961AC",
8
4
  "success-color": "#52c41a",
9
5
  "warning-color": "#faad14",
@@ -13,40 +9,44 @@ export class ThemeUtils {
13
9
  "primary-color-click": "#124B93"
14
10
  };
15
11
 
16
- private static cachedTheme: Record<string, string> | null = null;
12
+ static cachedTheme = null;
17
13
 
18
- static get theme(): Record<string, string> {
14
+ static get theme() {
19
15
  if (this.cachedTheme) return this.cachedTheme;
20
16
  this.cachedTheme = this.loadTheme();
21
17
  return this.cachedTheme;
22
18
  }
23
19
 
24
- private static loadTheme(): Record<string, string> {
25
- let custom: Record<string, string> = {};
20
+ /** 调亮/调暗十六进制颜色 */
21
+ static _lightenHex(hex, percent) {
22
+ const num = parseInt(hex.replace('#', ''), 16);
23
+ const r = num >> 16 & 255, g = num >> 8 & 255, b = num & 255;
24
+ const t = percent < 0 ? 0 : 255;
25
+ const p = Math.abs(percent) / 100;
26
+ return '#' + (0x1000000 + (Math.round((t - r) * p) + r) * 0x10000
27
+ + (Math.round((t - g) * p) + g) * 0x100 + (Math.round((t - b) * p) + b)).toString(16).slice(1);
28
+ }
29
+
30
+ static loadTheme() {
31
+ let custom = {};
26
32
  try {
27
33
  if (typeof OPEN_ADMIN_THEME !== 'undefined' && OPEN_ADMIN_THEME) {
28
34
  custom = OPEN_ADMIN_THEME;
29
35
  }
30
- } catch {}
31
-
36
+ } catch (e) {}
32
37
  const result = {...this.defaultTheme, ...custom};
33
-
34
- // Auto-derive hover/click from primary if not explicitly set
35
38
  if (custom["primary-color"]) {
36
39
  if (!custom["primary-color-hover"]) {
37
- result["primary-color-hover"] = ColorsUtils.lighten(result["primary-color"], 20);
40
+ result["primary-color-hover"] = ThemeUtils._lightenHex(result["primary-color"], 20);
38
41
  }
39
42
  if (!custom["primary-color-click"]) {
40
- result["primary-color-click"] = ColorsUtils.lighten(result["primary-color"], -10);
43
+ result["primary-color-click"] = ThemeUtils._lightenHex(result["primary-color"], -10);
41
44
  }
42
45
  }
43
-
44
46
  return result;
45
47
  }
46
48
 
47
- public static getColor(key: string): string | undefined {
49
+ static getColor(key) {
48
50
  return ThemeUtils.theme[key];
49
51
  }
50
52
  }
51
-
52
-
@@ -1,7 +1,6 @@
1
1
  export * from './DictUtils'
2
2
  export * from './PermUtils'
3
3
  export * from './PageUtils'
4
- export * from "./SysUtils"
5
4
  export * from './HttpUtils'
6
- export * from './FormRegistryUtils'
5
+ export * from './FormRegistry'
7
6
  export * from './ThemeUtils'
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import {Carousel, Empty} from 'antd';
3
+ import {UrlUtils} from '../../utils';
3
4
 
4
5
 
5
6
  export class ViewFile extends React.Component {
@@ -14,7 +15,7 @@ export class ViewFile extends React.Component {
14
15
 
15
16
  const arr = fileId.split(',');
16
17
 
17
- const urlList = arr.map(id => 'admin/sysFile/preview/' + id);
18
+ const urlList = arr.map(id => UrlUtils.contextPath('/admin/sysFile/preview/' + id));
18
19
  const height = this.props.height;
19
20
 
20
21
  if(urlList.length === 1){
@@ -29,9 +30,8 @@ export class ViewFile extends React.Component {
29
30
 
30
31
  // 多个文件则用走马灯
31
32
  const iframeList = urlList.map((url) => {
32
- return <div style={{height}}>
33
+ return <div key={url} style={{height}}>
33
34
  <iframe
34
- key={url}
35
35
  src={url}
36
36
  width='99%'
37
37
  frameBorder={0}
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import {Modal} from 'antd';
3
- import {SysUtils} from '../../utils';
3
+ import {UrlUtils} from '../../utils';
4
4
 
5
5
 
6
6
  export class ViewImage extends React.Component {
@@ -27,11 +27,11 @@ export class ViewImage extends React.Component {
27
27
  }
28
28
 
29
29
  if (isId) {
30
- urlList.push(SysUtils.contextPath('/admin/sysFile/preview/' + v));
30
+ urlList.push(UrlUtils.contextPath('/admin/sysFile/preview/' + v));
31
31
  continue;
32
32
  }
33
33
 
34
- urlList.push(SysUtils.contextPath(v));
34
+ urlList.push(UrlUtils.contextPath(v));
35
35
  }
36
36
 
37
37
  const imgs = urlList.map((url) => (
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Tag } from 'antd';
3
3
 
4
- export class ViewBooleanEnableDisable extends React.Component {
4
+ export class ViewSwitch extends React.Component {
5
5
 
6
6
  render() {
7
7
  const { value } = this.props;
@@ -3,10 +3,9 @@ export * from './types';
3
3
  export * from './ViewPassword';
4
4
  export * from './ViewBoolean';
5
5
  export * from './ViewApproveStatus'
6
- export * from './ViewProcessInstanceProgress'
7
- export * from './ViewProcessInstanceProgressButton'
8
- export * from './ViewBooleanEnableDisable'
6
+ export * from './ViewSwitch'
9
7
  export * from './ViewImage'
10
8
  export * from './ViewFile'
11
9
  export * from './ViewText'
12
- export * from './ViewFileButton'
10
+ export * from './ViewFileButton'
11
+ export * from './ViewRange'
@@ -1,11 +1,8 @@
1
- import {Badge, Dropdown} from "antd";
2
- import {NotificationOutlined, SettingOutlined, UserOutlined} from "@ant-design/icons";
1
+ import {Avatar, Dropdown} from "antd";
3
2
  import React from "react";
4
3
  import {history} from "umi";
5
- import {DeviceUtils, HttpUtils, MessageUtils, PageUtils, SysUtils} from "../../framework";
4
+ import {DeviceUtils, HttpUtils, MessageUtils, PageUtils, GlobalData} from "../../framework";
6
5
 
7
-
8
- const ID = 'header-right';
9
6
  export class HeaderRight extends React.Component {
10
7
 
11
8
  state = {
@@ -13,7 +10,6 @@ export class HeaderRight extends React.Component {
13
10
  };
14
11
 
15
12
  componentDidMount() {
16
- document.dispatchEvent(new CustomEvent('componentDidMount', {detail: ID}))
17
13
  if (DeviceUtils.isMobileDevice()) {
18
14
  this.setState({isMobileDevice: true})
19
15
  }
@@ -36,12 +32,12 @@ export class HeaderRight extends React.Component {
36
32
  })
37
33
  }
38
34
 
39
- userCenter = () => {
40
- PageUtils.open('/userCenter', '个人中心')
35
+ account = () => {
36
+ PageUtils.open('/account', '个人中心')
41
37
  }
42
38
 
43
39
  render() {
44
- const info = SysUtils.getLoginInfo()
40
+ const info = GlobalData.getLoginInfo()
45
41
 
46
42
  if (this.state.isMobileDevice) {
47
43
  return <div className='header-right'>
@@ -51,44 +47,33 @@ export class HeaderRight extends React.Component {
51
47
 
52
48
  return <div className='header-right'>
53
49
 
54
- <div className='item'>
55
- <UserOutlined/> {info.name}
56
- </div>
57
-
58
-
59
- <div className='item' onClick={() => PageUtils.open('/userCenter/message', '我的消息')}>
60
- <Badge count={info.messageCount} size="small">
61
- <NotificationOutlined/>
62
- </Badge>
63
- </div>
64
-
65
- <div className='item'>
66
-
67
- <Dropdown menu={{
68
- onClick: ({key}) => {
69
- switch (key) {
70
- case 'userCenter':
71
- this.userCenter()
72
- break;
73
- case 'logout':
74
- this.logout();
75
- break;
76
- case 'about':
77
- this.about()
78
- break
79
- }
80
- },
81
- items: [
82
- {key: 'userCenter', label: '个人中心'},
83
- {key: 'about', label: '关于系统'},
84
- {key: 'logout', label: '退出登录'},
85
-
86
- ]
87
- }}><SettingOutlined/>
88
-
89
- </Dropdown>
90
-
91
- </div>
50
+ <Dropdown menu={{
51
+ onClick: ({key}) => {
52
+ switch (key) {
53
+ case 'account':
54
+ this.account()
55
+ break;
56
+ case 'logout':
57
+ this.logout();
58
+ break;
59
+ case 'about':
60
+ this.about()
61
+ break
62
+ }
63
+ },
64
+ items: [
65
+ {key: 'account', label: '个人中心'},
66
+ {key: 'about', label: '关于系统'},
67
+ {key: 'logout', label: '退出登录'},
68
+ ]
69
+ }}>
70
+ <div className='item' style={{cursor: 'pointer'}}>
71
+ <Avatar size="small" style={{backgroundColor: '#1677ff', verticalAlign: 'middle'}}>
72
+ {info.name?.charAt(0)}
73
+ </Avatar>
74
+ <span style={{marginLeft: 8}}>{info.name}</span>
75
+ </div>
76
+ </Dropdown>
92
77
 
93
78
  </div>
94
79
  }
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
- import {Badge, Layout, Menu, Skeleton, Watermark} from 'antd';
2
+ import {Layout, Menu, Skeleton, Watermark} from 'antd';
3
3
 
4
4
  import {history, Link} from 'umi';
5
5
  import "./index.less"
6
- import {ErrorBoundary, HttpUtils, NamedIcon, PageUtils, SysUtils, ThemeUtils, TreeUtils} from "../../framework";
6
+ import {HttpUtils, NamedIcon, PageUtils, GlobalData, ThemeUtils, TreeUtils} from "../../framework";
7
7
 
8
8
  import { HeaderRight } from "./HeaderRight";
9
9
  import { TabPageRender } from "./TabPageRender";
@@ -37,8 +37,8 @@ export default class extends React.Component {
37
37
  // 判断是否手机端,自动收起菜单
38
38
 
39
39
 
40
- const siteInfo = SysUtils.getSiteInfo();
41
- const loginInfo = SysUtils.getLoginInfo()
40
+ const siteInfo = GlobalData.getSiteInfo();
41
+ const loginInfo = GlobalData.getLoginInfo()
42
42
  this.setState({siteInfo, loginInfo})
43
43
 
44
44
  this.initMenu()
@@ -84,7 +84,6 @@ export default class extends React.Component {
84
84
 
85
85
  this.setState({menuTree, pathMenuMap, topMenus, sideMenus, activeTopMenuKey, currentMenuKey})
86
86
 
87
- this.loadBadge(menuMap)
88
87
  }).catch(err => {
89
88
  console.error('加载菜单失败:', err)
90
89
  this.setState({menuTree: [], topMenus: [], sideMenus: []})
@@ -170,27 +169,6 @@ export default class extends React.Component {
170
169
  );
171
170
  }
172
171
 
173
- loadBadge = menuMap => {
174
- for (let id in menuMap) {
175
- const item = menuMap[id]
176
- const {messageCountUrl} = item;
177
- if (!messageCountUrl) {
178
- continue
179
- }
180
- HttpUtils.get(messageCountUrl).then(rs => {
181
- const {menuTree} = this.state
182
- const menu = TreeUtils.findByKey(id, menuTree, 'key')
183
- if (menu) {
184
- menu.icon = <Badge dot count={rs} size={"small"}>{menu.icon}</Badge>
185
- this.setState({menuTree: [...menuTree]})
186
- }
187
- }).catch(e => {
188
- console.error('[Layout] 加载消息数失败:', e);
189
- })
190
- }
191
- };
192
-
193
-
194
172
  render() {
195
173
  const {siteInfo, loginInfo} = this.state
196
174
 
@@ -217,9 +195,7 @@ export default class extends React.Component {
217
195
  </Header>
218
196
 
219
197
  <Content id='admin-layout-content'>
220
- <ErrorBoundary>
221
- {this.renderCenterContent(loginInfo)}
222
- </ErrorBoundary>
198
+ {this.renderCenterContent(loginInfo)}
223
199
  </Content>
224
200
 
225
201
  </Layout>
@@ -3,10 +3,11 @@ import {App, ConfigProvider} from "antd";
3
3
  import zhCN from 'antd/locale/zh_CN';
4
4
  import dayjs from 'dayjs';
5
5
  import 'dayjs/locale/zh-cn';
6
- import {Outlet, useLocation} from "umi";
6
+ import {Outlet, useLocation, history} from "umi";
7
7
 
8
8
  import AdminLayout from "./admin"
9
- import {HttpUtils, PageLoading, PageUtils, SysUtils, ThemeUtils} from "../framework";
9
+ import {HttpUtils, PageLoading, PageUtils, GlobalData, ThemeUtils, DownloadModal} from "../framework";
10
+ import {ErrorBoundary} from "../framework";
10
11
 
11
12
  import '../style/global.less'
12
13
  import './index.less'
@@ -36,12 +37,12 @@ const configProps = {
36
37
  };
37
38
 
38
39
  function AppWrapper({children}) {
39
- return <ConfigProvider {...configProps}><App>{children}</App></ConfigProvider>;
40
+ return <ConfigProvider {...configProps}><App><DownloadModal />{children}</App></ConfigProvider>;
40
41
  }
41
42
 
42
43
  const PUBLIC_PAGES = (() => {
43
44
  const raw = typeof OPEN_ADMIN_PUBLIC_PAGES !== 'undefined' && OPEN_ADMIN_PUBLIC_PAGES;
44
- return raw ? raw.split(',').map(s => s.trim()) : ['/login', '/test'];
45
+ return raw ? raw.split(',').map(s => s.trim()) : ['/login', '/test', '/forceUpdatePwd'];
45
46
  })();
46
47
 
47
48
  function isPublicPage(pathname, search) {
@@ -60,7 +61,8 @@ function isPublicPage(pathname, search) {
60
61
  }
61
62
 
62
63
  export function Layouts() {
63
- const {pathname, search} = useLocation();
64
+ const location = useLocation();
65
+ const {pathname, search} = location;
64
66
  const [siteInfoLoaded, setSiteInfoLoaded] = useState(false);
65
67
  const [loginChecked, setLoginChecked] = useState(false);
66
68
 
@@ -77,31 +79,39 @@ export function Layouts() {
77
79
 
78
80
  Promise.all([
79
81
  HttpUtils.get("/admin/public/site-info").then(data => {
80
- SysUtils.setSiteInfo(data);
82
+ GlobalData.setSiteInfo(data);
81
83
  setSiteInfoLoaded(true);
82
84
  }),
83
- HttpUtils.get('/admin/public/check-login').then(data => {
84
- SysUtils.setDictInfo(data.dictInfo);
85
- SysUtils.setLoginInfo(data.loginInfo);
85
+ HttpUtils.get('/admin/public/user-info').then(data => {
86
+ GlobalData.setDictInfo(data.dictInfo);
87
+ GlobalData.setLoginInfo(data.loginInfo);
88
+
89
+ if (data.needUpdatePwd && pathname !== '/forceUpdatePwd') {
90
+ history.push('/forceUpdatePwd');
91
+ return;
92
+ }
93
+
86
94
  setLoginChecked(true);
87
95
  }),
88
96
  ]).catch(() => {
89
97
  console.error('[Layout] 初始化应用失败');
90
98
  PageUtils.redirectToLogin();
91
99
  });
92
- }, [pathname]);
100
+ }, [location]);
93
101
 
94
- if (isPublic) return <AppWrapper><Outlet/></AppWrapper>;
102
+ if (isPublic) return <ErrorBoundary minimal><AppWrapper><Outlet/></AppWrapper></ErrorBoundary>;
95
103
 
96
104
  return (
97
- <AppWrapper>
98
- {ready ? <AdminLayout/> : (
99
- <PageLoading messages={[
100
- !siteInfoLoaded && '加载站点信息...',
101
- !loginChecked && '检查登录中...',
102
- ].filter(Boolean)}/>
103
- )}
104
- </AppWrapper>
105
+ <ErrorBoundary minimal>
106
+ <AppWrapper>
107
+ {ready ? <AdminLayout/> : (
108
+ <PageLoading messages={[
109
+ !siteInfoLoaded && '加载站点信息...',
110
+ !loginChecked && '检查登录中...',
111
+ ].filter(Boolean)}/>
112
+ )}
113
+ </AppWrapper>
114
+ </ErrorBoundary>
105
115
  );
106
116
  }
107
117
 
@@ -3,7 +3,6 @@ import {Page} from "../framework";
3
3
 
4
4
  export default class extends React.Component {
5
5
 
6
-
7
6
  render() {
8
7
  return <Page title="关于" description="了解系统版本与相关信息">
9
8
  <h1>关于</h1>
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import {Button, Form, Input, Modal} from "antd";
3
3
  import {history} from 'umi'
4
- import {HttpUtils, SysUtils} from "../../framework";
4
+ import {HttpUtils} from "../../framework";
5
5
 
6
6
  export default class extends React.Component {
7
7
 
@@ -12,7 +12,6 @@ export default class extends React.Component {
12
12
  title: '提示',
13
13
  content: '修改密码成功',
14
14
  onOk: () => {
15
- SysUtils.setToken(null)
16
15
  history.push('/login')
17
16
  }
18
17
  })
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
  import {Avatar, Card, Col, Row, Tabs} from "antd";
3
- import ChangePassword from "./ChangePassword";
3
+ import ChangePassword from "./changePassword";
4
4
  import {HttpUtils, Page} from "../../framework";
5
5
 
6
6
  export default class extends React.Component {
@@ -71,11 +71,7 @@ export default class extends React.Component {
71
71
  <ChangePassword/>
72
72
  </div>
73
73
  },
74
- {
75
- label: '消息订阅', key: 'topic', children: <div>
76
- 当账号管理邮箱后,系统消息会发送邮件给您
77
- </div>
78
- }
74
+
79
75
  ]}
80
76
  tabPlacement='left'
81
77
  >
@@ -0,0 +1,89 @@
1
+ import React from "react";
2
+ import {Button, Form, Input, message} from "antd";
3
+ import {history} from 'umi'
4
+ import {HttpUtils, PageUtils, GlobalData} from "../framework";
5
+
6
+ export default class extends React.Component {
7
+
8
+ state = {
9
+ checking: true
10
+ }
11
+
12
+ async componentDidMount() {
13
+ try {
14
+ const rs = await HttpUtils.get('/admin/public/user-info', null, {showError: false});
15
+ if (!rs.login) {
16
+ PageUtils.redirectToLogin();
17
+ return;
18
+ }
19
+ GlobalData.setLoginInfo(rs.loginInfo);
20
+ this.setState({checking: false});
21
+ } catch (e) {
22
+ PageUtils.redirectToLogin();
23
+ }
24
+ }
25
+
26
+ onFinish = (values) => {
27
+ HttpUtils.post('admin/userCenter/update-pwd', values).then(() => {
28
+ message.success('修改密码成功,请重新登录');
29
+ history.push('/login');
30
+ })
31
+ }
32
+
33
+ validator = (rule, value) => {
34
+ return new Promise((resolve, reject) => {
35
+ HttpUtils.get("admin/sysUser/pwd-strength", {password: value}).then(response => {
36
+ const rs = response.data
37
+ if (!rs.success) {
38
+ reject(rs.message)
39
+ }
40
+ resolve()
41
+ })
42
+ })
43
+ }
44
+
45
+ render() {
46
+ if (this.state.checking) return null;
47
+
48
+ return (
49
+ <div style={{
50
+ display: 'flex',
51
+ justifyContent: 'center',
52
+ alignItems: 'center',
53
+ minHeight: '100vh',
54
+ background: '#f0f2f5'
55
+ }}>
56
+ <div style={{
57
+ background: '#fff',
58
+ padding: '40px',
59
+ borderRadius: '8px',
60
+ boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
61
+ maxWidth: 400,
62
+ width: '100%'
63
+ }}>
64
+ <h2 style={{textAlign: 'center', marginBottom: 24}}>修改密码</h2>
65
+ <p style={{textAlign: 'center', color: '#999', marginBottom: 24}}>
66
+ 首次登录或密码已被重置,请修改密码后重新登录
67
+ </p>
68
+ <Form onFinish={this.onFinish}>
69
+ <Form.Item name='newPassword'
70
+ label='新密码'
71
+ extra={'请输入字母、数字、特殊字符'}
72
+ rules={[
73
+ {required: true, message: '请输入新密码'},
74
+ {validator: this.validator}
75
+ ]}
76
+ >
77
+ <Input.Password/>
78
+ </Form.Item>
79
+ <Form.Item style={{marginTop: 40}}>
80
+ <Button type="primary" htmlType="submit" block size='large'>
81
+ 确定
82
+ </Button>
83
+ </Form.Item>
84
+ </Form>
85
+ </div>
86
+ </div>
87
+ )
88
+ }
89
+ }
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import {Button, Form, Input, message} from 'antd';
3
3
  import {LockOutlined, UserOutlined, WarningOutlined} from '@ant-design/icons';
4
4
  import {history} from 'umi';
5
- import {EventBusUtils, HttpUtils, PageUtils, SysUtils} from "../framework/utils";
5
+ import {EventBus, HttpUtils, PageUtils, GlobalData} from "../framework";
6
6
 
7
7
  import "./login.less"
8
8
 
@@ -19,7 +19,7 @@ function getRedirect() {
19
19
  function postLogin(values) {
20
20
  return new Promise((resolve, reject) => {
21
21
  HttpUtils.post('/admin/auth/login', values).then(rs => {
22
- EventBusUtils.emit('loginSuccess')
22
+ EventBus.emit('loginSuccess')
23
23
  history.push(getRedirect())
24
24
  resolve(rs)
25
25
  }).catch(e => {
@@ -44,15 +44,15 @@ export default class extends React.Component {
44
44
  }
45
45
 
46
46
  async componentDidMount() {
47
- const siteInfo = SysUtils.getSiteInfo()
47
+ const siteInfo = GlobalData.getSiteInfo()
48
48
  if (siteInfo && siteInfo.title) {
49
49
  this.setState({siteInfo})
50
50
  return
51
51
  }
52
52
  // localStorage 中无站点信息,从服务端重新加载
53
53
  try {
54
- const rs = await HttpUtils.get('/admin/public/site-info')
55
- SysUtils.setSiteInfo(rs)
54
+ const rs = await HttpUtils.get('/admin/public/site-info', null, { showError: false })
55
+ GlobalData.setSiteInfo(rs)
56
56
  this.setState({siteInfo: rs})
57
57
  } catch (e) {
58
58
  console.error('[Login] 加载站点信息失败:', e);
@@ -2,13 +2,13 @@ import {DeleteOutlined, EditOutlined, PlusOutlined} from '@ant-design/icons';
2
2
  import {Button, Card, Descriptions, Empty, Form, Input, InputNumber, Modal, Popconfirm, Splitter, Tree, Tag, TreeSelect, Typography} from 'antd';
3
3
  import React from 'react';
4
4
  import {
5
- ButtonList,
5
+ PermActions,
6
6
  FieldBoolean,
7
7
  FieldDictSelect,
8
8
  HttpUtils,
9
9
  Page,
10
10
  ProTable,
11
- ViewBooleanEnableDisable,
11
+ ViewSwitch,
12
12
  } from "../../../framework";
13
13
 
14
14
  export default class extends React.Component {
@@ -139,7 +139,7 @@ export default class extends React.Component {
139
139
  {
140
140
  title: '启用', dataIndex: 'enabled',
141
141
  render(v) {
142
- return <ViewBooleanEnableDisable value={v}/>
142
+ return <ViewSwitch value={v}/>
143
143
  }
144
144
  },
145
145
  {title: '序号', dataIndex: 'seq'},
@@ -147,14 +147,14 @@ export default class extends React.Component {
147
147
  title: '操作', dataIndex: 'option',
148
148
  render: (_, record) => {
149
149
  return (
150
- <ButtonList>
150
+ <PermActions>
151
151
  <Button size='small' perm='sys-dict:update'
152
152
  onClick={() => this.handleItemEdit(record)}>编辑</Button>
153
153
  <Popconfirm perm='sys-dict:delete' title='是否确定删除字典项'
154
154
  onConfirm={() => this.handleItemDelete(record)}>
155
155
  <Button size='small'>删除</Button>
156
156
  </Popconfirm>
157
- </ButtonList>
157
+ </PermActions>
158
158
  );
159
159
  },
160
160
  },
@@ -204,7 +204,7 @@ export default class extends React.Component {
204
204
  <Descriptions.Item label="类型编码">{selectedType.typeCode}</Descriptions.Item>
205
205
  <Descriptions.Item label="分类">{this.getParentLabel() || '-'}</Descriptions.Item>
206
206
  <Descriptions.Item label="序号">{selectedType.seq}</Descriptions.Item>
207
- <Descriptions.Item label="启用"><ViewBooleanEnableDisable value={selectedType.enabled}/></Descriptions.Item>
207
+ <Descriptions.Item label="启用"><ViewSwitch value={selectedType.enabled}/></Descriptions.Item>
208
208
  </Descriptions>}
209
209
  </Card>
210
210
  <Card size='small'>