@jiangood/open-admin 2.5.8 → 3.0.0

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 (142) hide show
  1. package/package.json +20 -8
  2. package/src/framework/GlobalData.ts +85 -0
  3. package/src/framework/biz/OrgTree.tsx +2 -7
  4. package/src/framework/biz/Perm.tsx +11 -0
  5. package/src/framework/biz/PermActions.tsx +18 -15
  6. package/src/framework/biz/index.tsx +34 -19
  7. package/src/framework/components/ContextMenu/index.tsx +105 -78
  8. package/src/framework/components/DownloadModal/index.tsx +15 -17
  9. package/src/framework/components/ErrorBoundary/index.tsx +2 -2
  10. package/src/framework/components/FormModal/index.tsx +76 -0
  11. package/src/framework/components/Gap/index.tsx +1 -1
  12. package/src/framework/components/NamedIcon/index.tsx +55 -9
  13. package/src/framework/components/Page/index.less +0 -1
  14. package/src/framework/components/Page/index.tsx +34 -27
  15. package/src/framework/components/PageLoading/index.less +15 -0
  16. package/src/framework/components/PageLoading/index.tsx +32 -16
  17. package/src/framework/components/ProTable/index.tsx +86 -15
  18. package/src/framework/components/index.ts +1 -0
  19. package/src/framework/config/index.ts +1 -0
  20. package/src/framework/config/themeConfig.ts +39 -0
  21. package/src/framework/fields/FieldBoolean/index.tsx +11 -2
  22. package/src/framework/fields/FieldDate/index.tsx +22 -7
  23. package/src/framework/fields/FieldDateRange/index.tsx +24 -6
  24. package/src/framework/fields/FieldDictSelect/index.tsx +1 -0
  25. package/src/framework/fields/FieldEditor/index.tsx +7 -1
  26. package/src/framework/fields/FieldNumberRange/index.tsx +14 -5
  27. package/src/framework/fields/FieldPercent/index.tsx +16 -5
  28. package/src/framework/fields/FieldRemoteSelect/index.tsx +4 -2
  29. package/src/framework/fields/FieldRemoteTreeSelect/index.tsx +2 -1
  30. package/src/framework/fields/FieldSysOrgTree/index.tsx +6 -1
  31. package/src/framework/fields/FieldSysOrgTreeSelect/index.tsx +6 -1
  32. package/src/framework/fields/FieldTable/index.tsx +35 -6
  33. package/src/framework/fields/FieldTableSelect/index.tsx +18 -2
  34. package/src/framework/fields/FieldUploadFile/index.tsx +69 -28
  35. package/src/framework/fields/index.ts +0 -1
  36. package/src/framework/index.ts +2 -0
  37. package/src/framework/router/Link.tsx +26 -0
  38. package/src/framework/router/PageFrame.tsx +31 -0
  39. package/src/framework/router/history.ts +50 -0
  40. package/src/framework/router/index.ts +4 -0
  41. package/src/framework/router/matcher.ts +58 -0
  42. package/src/framework/utils/{ArrayUtils.js → ArrayUtils.ts} +5 -5
  43. package/src/framework/utils/{DateUtils.js → DateUtils.ts} +19 -19
  44. package/src/framework/utils/{DeviceUtils.js → DeviceUtils.ts} +8 -1
  45. package/src/framework/utils/{EventBus.js → EventBus.ts} +13 -6
  46. package/src/framework/utils/MessageApi.ts +5 -0
  47. package/src/framework/utils/ModalApi.ts +5 -0
  48. package/src/framework/utils/ObjectUtils.ts +15 -0
  49. package/src/framework/utils/{StorageUtils.js → StorageUtils.ts} +7 -7
  50. package/src/framework/utils/{StringUtils.js → StringUtils.ts} +15 -15
  51. package/src/framework/utils/{TreeUtils.js → TreeUtils.ts} +19 -12
  52. package/src/framework/utils/{UrlUtils.js → UrlUtils.ts} +10 -10
  53. package/src/framework/utils/index.ts +2 -1
  54. package/src/framework/utils/system/{DictUtils.js → DictUtils.ts} +16 -4
  55. package/src/framework/utils/system/{HttpUtils.js → HttpUtils.ts} +25 -21
  56. package/src/framework/utils/system/PageUtils.ts +49 -0
  57. package/src/framework/utils/system/{PermUtils.js → PermUtils.ts} +5 -6
  58. package/src/framework/utils/system/index.ts +0 -2
  59. package/src/framework/views/ViewBoolean/index.tsx +6 -3
  60. package/src/framework/views/ViewFileButton/index.tsx +13 -8
  61. package/src/framework/views/ViewImage/index.tsx +19 -14
  62. package/src/framework/views/ViewRange/index.tsx +10 -7
  63. package/src/framework/views/ViewText/index.tsx +9 -11
  64. package/src/layouts/admin/AdminTabs.jsx +79 -0
  65. package/src/layouts/admin/AdminTabs.less +63 -0
  66. package/src/layouts/admin/HeaderRight.jsx +66 -33
  67. package/src/layouts/admin/TabLayout.jsx +124 -0
  68. package/src/layouts/admin/index.jsx +12 -5
  69. package/src/layouts/admin/index.less +5 -83
  70. package/src/layouts/index.tsx +148 -0
  71. package/src/main.jsx +8 -0
  72. package/src/pages/account/changePassword.jsx +14 -10
  73. package/src/pages/article/$code.jsx +43 -0
  74. package/src/pages/index.jsx +6 -4
  75. package/src/pages/{login.jsx → public/login.jsx} +7 -10
  76. package/src/pages/public/test.jsx +30 -0
  77. package/src/pages/{forceUpdatePwd.jsx → standalone/forceUpdatePwd.jsx} +3 -32
  78. package/src/pages/system/article/index.jsx +147 -0
  79. package/src/pages/system/dict/index.jsx +60 -91
  80. package/src/pages/system/file/index.jsx +23 -17
  81. package/src/pages/system/job/index.jsx +63 -72
  82. package/src/pages/system/log/index.jsx +11 -8
  83. package/src/pages/system/org/index.jsx +60 -80
  84. package/src/pages/system/role/index.jsx +50 -86
  85. package/src/pages/system/role/rolePerm.jsx +2 -2
  86. package/src/pages/system/user/index.jsx +120 -73
  87. package/src/pages/system/user/userPerm.jsx +2 -2
  88. package/vite-plugin/index.js +107 -0
  89. package/config/common-plugin.js +0 -145
  90. package/config/config.js +0 -5
  91. package/config/utils.js +0 -73
  92. package/src/.umi-production/appData.json +0 -2237
  93. package/src/.umi-production/core/EmptyRoute.tsx +0 -9
  94. package/src/.umi-production/core/defineApp.ts +0 -16
  95. package/src/.umi-production/core/helmet.ts +0 -10
  96. package/src/.umi-production/core/helmetContext.ts +0 -4
  97. package/src/.umi-production/core/history.ts +0 -72
  98. package/src/.umi-production/core/historyIntelli.ts +0 -132
  99. package/src/.umi-production/core/plugin.ts +0 -40
  100. package/src/.umi-production/core/pluginConfig.ts +0 -330
  101. package/src/.umi-production/core/pluginConfigJoi.d.ts +0 -7
  102. package/src/.umi-production/core/polyfill.ts +0 -220
  103. package/src/.umi-production/core/route.tsx +0 -45
  104. package/src/.umi-production/core/routeProps.js +0 -5
  105. package/src/.umi-production/core/routeProps.ts +0 -6
  106. package/src/.umi-production/core/terminal.ts +0 -37
  107. package/src/.umi-production/exports.ts +0 -17
  108. package/src/.umi-production/testBrowser.tsx +0 -90
  109. package/src/.umi-production/tsconfig.json +0 -43
  110. package/src/.umi-production/typings.d.ts +0 -136
  111. package/src/.umi-production/umi.ts +0 -83
  112. package/src/framework/GlobalData.d.ts +0 -8
  113. package/src/framework/GlobalData.js +0 -33
  114. package/src/framework/biz/HasPerm.tsx +0 -14
  115. package/src/framework/fields/FieldRemoteSelectMultiple/index.tsx +0 -29
  116. package/src/framework/utils/ArrayUtils.d.ts +0 -6
  117. package/src/framework/utils/DateUtils.d.ts +0 -20
  118. package/src/framework/utils/DeviceUtils.d.ts +0 -3
  119. package/src/framework/utils/EventBus.d.ts +0 -6
  120. package/src/framework/utils/MessageUtils.d.ts +0 -10
  121. package/src/framework/utils/MessageUtils.js +0 -43
  122. package/src/framework/utils/ObjectUtils.d.ts +0 -14
  123. package/src/framework/utils/ObjectUtils.js +0 -12
  124. package/src/framework/utils/StorageUtils.d.ts +0 -4
  125. package/src/framework/utils/StringUtils.d.ts +0 -17
  126. package/src/framework/utils/TreeUtils.d.ts +0 -13
  127. package/src/framework/utils/UrlUtils.d.ts +0 -6
  128. package/src/framework/utils/system/DictUtils.d.ts +0 -20
  129. package/src/framework/utils/system/FormRegistry.d.ts +0 -8
  130. package/src/framework/utils/system/FormRegistry.js +0 -31
  131. package/src/framework/utils/system/HttpUtils.d.ts +0 -14
  132. package/src/framework/utils/system/PageUtils.d.ts +0 -14
  133. package/src/framework/utils/system/PageUtils.js +0 -59
  134. package/src/framework/utils/system/PermUtils.d.ts +0 -5
  135. package/src/framework/utils/system/ThemeUtils.d.ts +0 -6
  136. package/src/framework/utils/system/ThemeUtils.js +0 -52
  137. package/src/layouts/PageRender.tsx +0 -29
  138. package/src/layouts/admin/TabPageRender.jsx +0 -210
  139. package/src/layouts/index.jsx +0 -119
  140. package/src/loading.jsx +0 -19
  141. package/src/pages/about.jsx +0 -11
  142. /package/src/pages/{login.less → public/login.less} +0 -0
@@ -1,12 +1,11 @@
1
1
  import React from 'react';
2
2
  import {Layout, Menu, Skeleton, Watermark} from 'antd';
3
3
 
4
- import {history, Link} from 'umi';
5
4
  import "./index.less"
6
- import {HttpUtils, NamedIcon, PageUtils, GlobalData, ThemeUtils, TreeUtils} from "../../framework";
5
+ import {HttpUtils, NamedIcon, PageUtils, GlobalData, TreeUtils, history, Link, ARTICLE_HEADER_LEFT} from "../../framework";
7
6
 
8
7
  import { HeaderRight } from "./HeaderRight";
9
- import { TabPageRender } from "./TabPageRender";
8
+ import { TabLayout } from "./TabLayout";
10
9
  const {Header, Sider, Content} = Layout;
11
10
  /**
12
11
  * 带菜单的布局,主要处理布局宇框架结构
@@ -30,6 +29,7 @@ export default class extends React.Component {
30
29
 
31
30
  siteInfo: {},
32
31
 
32
+ headerLeftArticles: [],
33
33
  }
34
34
 
35
35
 
@@ -42,6 +42,9 @@ export default class extends React.Component {
42
42
  this.setState({siteInfo, loginInfo})
43
43
 
44
44
  this.initMenu()
45
+
46
+ const siteArticles = GlobalData.getSiteArticles();
47
+ this.setState({headerLeftArticles: siteArticles[ARTICLE_HEADER_LEFT] || []})
45
48
  }
46
49
 
47
50
 
@@ -172,7 +175,7 @@ export default class extends React.Component {
172
175
  render() {
173
176
  const {siteInfo, loginInfo} = this.state
174
177
 
175
- return <Layout className='main-layout' style={{'--primary-color': ThemeUtils.getColor("primary-color"), '--primary-color-click': ThemeUtils.getColor("primary-color-click")}}>
178
+ return <Layout className='main-layout'>
176
179
  <Sider id='left-sider'
177
180
  width={180}
178
181
  collapsible
@@ -191,6 +194,10 @@ export default class extends React.Component {
191
194
  <Layout style={{flex: 1, overflow: 'hidden'}}>
192
195
  <Header className='header'>
193
196
  {this.renderTopMenu()}
197
+ {this.state.headerLeftArticles.map(a => (
198
+ <div key={a.code} className='item' style={{cursor: 'pointer', padding: '0 12px', whiteSpace: 'nowrap'}}
199
+ onClick={() => PageUtils.open('/article/' + a.code, a.title)}>{a.title}</div>
200
+ ))}
194
201
  <HeaderRight/>
195
202
  </Header>
196
203
 
@@ -221,7 +228,7 @@ export default class extends React.Component {
221
228
  renderCenterContent = () => {
222
229
  const {siteInfo, loginInfo} = this.state
223
230
  // 即使菜单为空也直接显示页面内容,不要一直显示 Skeleton
224
- const tabPageRenderNode = <TabPageRender pathMenuMap={this.state.pathMenuMap}/>;
231
+ const tabPageRenderNode = <TabLayout pathMenuMap={this.state.pathMenuMap}/>;
225
232
  if (siteInfo.waterMark === true) {
226
233
  return <Watermark content={[loginInfo.name, loginInfo.account]}>
227
234
  {tabPageRenderNode}
@@ -7,6 +7,7 @@
7
7
  display: flex;
8
8
  align-items: center;
9
9
  background-color: #fff;
10
+ border-bottom: 1px solid #e8e8e8;
10
11
 
11
12
  .top-nav {
12
13
  flex: 1;
@@ -45,11 +46,13 @@
45
46
  flex-shrink: 0;
46
47
 
47
48
  .item {
49
+ display: inline-flex;
50
+ align-items: center;
48
51
  padding: 0 0.5rem;
49
52
  cursor: pointer;
50
53
 
51
54
  &:hover {
52
- background: var(--primary-color-click, #124B93);
55
+ background: var(--primary-color-hover, #4990CD);
53
56
  color: white;
54
57
  }
55
58
  }
@@ -105,88 +108,7 @@
105
108
  display: flex;
106
109
  flex-direction: column;
107
110
  overflow: hidden;
108
-
109
- .oa-tabs {
110
- flex: 1;
111
- display: flex;
112
- flex-direction: column;
113
- overflow: hidden;
114
-
115
- .oa-tab-bar {
116
- display: flex;
117
- flex-wrap: nowrap;
118
- overflow-x: auto;
119
- overflow-y: hidden;
120
- flex-shrink: 0;
121
- margin-bottom: 0;
122
- border-bottom: 1px solid #e8e8e8;
123
- background: #fff;
124
-
125
- &::-webkit-scrollbar {
126
- height: 0;
127
- }
128
- }
129
-
130
- .oa-tab {
131
- display: inline-flex;
132
- align-items: center;
133
- gap: 4px;
134
- padding: 0 12px;
135
- height: 32px;
136
- line-height: 32px;
137
- font-size: 13px;
138
- cursor: pointer;
139
- border-right: 1px solid #e8e8e8;
140
- white-space: nowrap;
141
- color: rgba(0, 0, 0, 0.65);
142
- background: #fafafa;
143
- transition: color 0.2s, background 0.2s;
144
- position: relative;
145
- flex-shrink: 0;
146
-
147
- &:hover {
148
- color: var(--primary-color, #1961AC);
149
- }
150
-
151
- &.active {
152
- color: var(--primary-color, #1961AC);
153
- background: #fff;
154
- font-weight: 500;
155
- }
156
-
157
- .oa-tab-label {
158
- max-width: 120px;
159
- overflow: hidden;
160
- text-overflow: ellipsis;
161
- }
162
-
163
- .oa-tab-close {
164
- display: inline-flex;
165
- align-items: center;
166
- justify-content: center;
167
- width: 16px;
168
- height: 16px;
169
- font-size: 12px;
170
- line-height: 1;
171
- border-radius: 50%;
172
- color: rgba(0, 0, 0, 0.45);
173
-
174
- &:hover {
175
- background: rgba(0, 0, 0, 0.08);
176
- color: rgba(0, 0, 0, 0.88);
177
- }
178
- }
179
- }
180
-
181
- .oa-tabs-content {
182
- flex: 1;
183
- overflow: hidden;
184
-
185
- .oa-tab-pane {
186
- height: 100%;
187
- }
188
- }
189
- }
111
+ flex: 1;
190
112
  }
191
113
  }
192
114
 
@@ -0,0 +1,148 @@
1
+ import React from "react";
2
+ import {ConfigProvider, Modal} from "antd";
3
+ import zhCN from 'antd/locale/zh_CN';
4
+ import dayjs from 'dayjs';
5
+ import 'dayjs/locale/zh-cn';
6
+ import {history, PageFrame} from "../framework";
7
+
8
+ import AdminLayout from "./admin"
9
+ import {HttpUtils, PageLoading, PageUtils, GlobalData, getThemeConfig, EventBus} from "../framework";
10
+ import {ErrorBoundary} from "../framework";
11
+
12
+ import '../style/global.less'
13
+ import './index.less'
14
+
15
+ dayjs.locale('zh-cn');
16
+
17
+ const configProps = {
18
+ input: {autoComplete: 'off'},
19
+ form: {validateMessages: {required: '必填项'}, colon: false},
20
+ button: {autoInsertSpace: false},
21
+ locale: zhCN,
22
+ theme: getThemeConfig(),
23
+ };
24
+
25
+ export class Layouts extends React.Component {
26
+ state = {
27
+ location: history.location,
28
+ siteInfoLoaded: false,
29
+ loginChecked: false,
30
+ loginExpiredVisible: false,
31
+ };
32
+
33
+ unlisten: (() => void) | null = null;
34
+ unsubscribeLoginExpired: (() => void) | null = null;
35
+
36
+ onLocationChange = ({location}: { location: typeof history.location }) => {
37
+ this.setState({location});
38
+ };
39
+
40
+ getPageType(pathname): 'public' | 'standalone' | 'protected' {
41
+ if (pathname === '/' || pathname === '/index') return 'protected';
42
+ if (pathname.startsWith('/public/')) return 'public';
43
+ if (pathname.startsWith('/standalone/')) return 'standalone';
44
+ return 'protected';
45
+ }
46
+
47
+ loadData() {
48
+ const {siteInfoLoaded, loginChecked} = this.state;
49
+ const pageType = this.getPageType(this.state.location.pathname);
50
+
51
+ if (!siteInfoLoaded) {
52
+ this.loadSiteInfo();
53
+ }
54
+
55
+ if ((pageType === 'protected' || pageType === 'standalone') && !loginChecked) {
56
+ this.loadLoginInfo();
57
+ }
58
+ }
59
+
60
+ loadSiteInfo() {
61
+ HttpUtils.get("/admin/public/site-info").then(data => {
62
+ GlobalData.setSiteInfo(data);
63
+ this.setState({siteInfoLoaded: true});
64
+ }).catch(() => {
65
+ console.error('[Layout] 加载站点信息失败');
66
+ });
67
+ }
68
+
69
+ loadLoginInfo() {
70
+ HttpUtils.get('/admin/public/login-info').then(data => {
71
+ GlobalData.setDictInfo(data.dictInfo);
72
+ GlobalData.setLoginInfo(data.loginInfo);
73
+ GlobalData.setSiteArticles(data.siteArticles);
74
+
75
+ if (data.needUpdatePwd) {
76
+ history.push('/standalone/forceUpdatePwd');
77
+ return;
78
+ }
79
+
80
+ this.setState({loginChecked: true});
81
+ }).catch(() => {
82
+ console.error('[Layout] 初始化应用失败');
83
+ PageUtils.redirectToLogin();
84
+ });
85
+ }
86
+
87
+ componentDidMount() {
88
+ this.unlisten = history.listen(this.onLocationChange);
89
+ this.unsubscribeLoginExpired = EventBus.on('loginExpired', () => {
90
+ if (!this.state.loginExpiredVisible) {
91
+ this.setState({loginExpiredVisible: true});
92
+ }
93
+ });
94
+ this.loadData();
95
+ }
96
+
97
+ componentDidUpdate(prevProps: {}, prevState: typeof this.state) {
98
+ if (this.state.location !== prevState.location) {
99
+ this.loadData();
100
+ }
101
+ }
102
+
103
+ componentWillUnmount() {
104
+ if (this.unlisten) {
105
+ this.unlisten();
106
+ }
107
+ if (this.unsubscribeLoginExpired) {
108
+ this.unsubscribeLoginExpired();
109
+ }
110
+ }
111
+
112
+ render() {
113
+ const {location, siteInfoLoaded, loginChecked} = this.state;
114
+ const {pathname, search} = location;
115
+ const ready = siteInfoLoaded && loginChecked;
116
+ const pageType = this.getPageType(pathname);
117
+ const showPageFrame = pageType === 'public' || (pageType === 'standalone' && ready);
118
+
119
+ return (
120
+ <ErrorBoundary minimal>
121
+ <ConfigProvider {...configProps}>
122
+ {showPageFrame ? <PageFrame url={pathname + search}/> : ready ? <AdminLayout/> : (
123
+ <PageLoading messages={[
124
+ !siteInfoLoaded && '加载站点信息...',
125
+ !loginChecked && '检查登录中...',
126
+ ].filter(Boolean)}/>
127
+ )}
128
+ {this.renderLoginExpiredModal()}
129
+ </ConfigProvider>
130
+ </ErrorBoundary>
131
+ );
132
+ }
133
+
134
+ renderLoginExpiredModal() {
135
+ return (
136
+ <Modal open={this.state.loginExpiredVisible} title="确认操作" okText="确定"
137
+ onCancel={() => this.setState({loginExpiredVisible: false})}
138
+ onOk={() => {
139
+ this.setState({loginExpiredVisible: false});
140
+ PageUtils.redirectToLogin();
141
+ }}>
142
+ 登录已过期,请重新登录
143
+ </Modal>
144
+ );
145
+ }
146
+ }
147
+
148
+ export default Layouts;
package/src/main.jsx ADDED
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import {createRoot} from 'react-dom/client';
3
+ import routes from 'virtual:open-admin/routes';
4
+ import {registerRoutes} from './framework';
5
+ import App from './layouts';
6
+
7
+ registerRoutes(routes);
8
+ createRoot(document.getElementById('root')).render(<App/>);
@@ -1,26 +1,22 @@
1
1
  import React from "react";
2
2
  import {Button, Form, Input, Modal} from "antd";
3
- import {history} from 'umi'
4
- import {HttpUtils} from "../../framework";
3
+ import {HttpUtils, history} from "../../framework";
5
4
 
6
5
  export default class extends React.Component {
7
6
 
7
+ state = {
8
+ successModalOpen: false,
9
+ };
8
10
 
9
11
  onFinish = (values) => {
10
12
  HttpUtils.post('admin/userCenter/update-pwd', values).then(() => {
11
- Modal.success({
12
- title: '提示',
13
- content: '修改密码成功',
14
- onOk: () => {
15
- history.push('/login')
16
- }
17
- })
13
+ this.setState({successModalOpen: true});
18
14
  })
19
15
  }
20
16
 
21
17
  validator = (rule, value) => {
22
18
  return new Promise((resolve, reject) => {
23
- HttpUtils.get("admin/sysUser/pwd-strength", {password: value}).then(response => {
19
+ HttpUtils.get("admin/sysUser/pwd-strength", {password: value}, {showError: false}).then(response => {
24
20
  const rs = response.data
25
21
  if (!rs.success) {
26
22
  reject(rs.message)
@@ -33,6 +29,14 @@ export default class extends React.Component {
33
29
 
34
30
  render() {
35
31
  return <div>
32
+ <Modal open={this.state.successModalOpen} title="提示" okText="确定"
33
+ onCancel={() => this.setState({successModalOpen: false})}
34
+ onOk={() => {
35
+ this.setState({successModalOpen: false});
36
+ history.push('/public/login');
37
+ }}>
38
+ 修改密码成功
39
+ </Modal>
36
40
 
37
41
  <Form onFinish={this.onFinish} style={{maxWidth: 400}}>
38
42
 
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import {HttpUtils, Page} from "../../framework";
3
+
4
+ export default class extends React.Component {
5
+
6
+ state = {
7
+ article: null,
8
+ loading: true,
9
+ }
10
+
11
+ componentDidMount() {
12
+ const code = this.props.params?.code
13
+ if (code) {
14
+ HttpUtils.get('admin/article/getByCode', {code}).then(rs => {
15
+ this.setState({article: rs, loading: false})
16
+ }).catch(() => {
17
+ this.setState({loading: false})
18
+ })
19
+ } else {
20
+ this.setState({loading: false})
21
+ }
22
+ }
23
+
24
+ render() {
25
+ const {article, loading} = this.state
26
+
27
+ if (loading) {
28
+ return <Page title="加载中...">
29
+ <div>加载中...</div>
30
+ </Page>
31
+ }
32
+
33
+ if (!article) {
34
+ return <Page title="文章不存在">
35
+ <div>文章不存在或已禁用</div>
36
+ </Page>
37
+ }
38
+
39
+ return <Page title={article.title}>
40
+ <div dangerouslySetInnerHTML={{__html: article.content}}/>
41
+ </Page>
42
+ }
43
+ }
@@ -2,8 +2,10 @@ import React from "react";
2
2
  import {Card} from "antd";
3
3
  import {Page} from "../framework";
4
4
 
5
- export default function () {
6
- return <Page title="首页" description="欢迎使用本系统">
7
- <Card>欢迎使用本系统</Card>
8
- </Page>
5
+ export default class extends React.Component {
6
+ render() {
7
+ return <Page title="首页" description="欢迎使用本系统">
8
+ <Card>欢迎使用本系统</Card>
9
+ </Page>
10
+ }
9
11
  }
@@ -1,26 +1,23 @@
1
1
  import React from 'react';
2
2
  import {Button, Form, Input, message} from 'antd';
3
3
  import {LockOutlined, UserOutlined, WarningOutlined} from '@ant-design/icons';
4
- import {history} from 'umi';
5
- import {EventBus, HttpUtils, PageUtils, GlobalData} from "../framework";
4
+ import {EventBus, HttpUtils, GlobalData, history} from "../../framework";
6
5
 
7
6
  import "./login.less"
8
7
 
9
- function getRedirect() {
10
- let redirect = PageUtils.currentParams()['redirect'];
11
- if (redirect) {
12
- redirect = decodeURIComponent(redirect)
13
- } else {
8
+ function getRedirect(query) {
9
+ let redirect = query?.redirect;
10
+ if (!redirect) {
14
11
  redirect = '/'
15
12
  }
16
13
  return redirect;
17
14
  }
18
15
 
19
- function postLogin(values) {
16
+ function postLogin(values, query) {
20
17
  return new Promise((resolve, reject) => {
21
18
  HttpUtils.post('/admin/auth/login', values).then(rs => {
22
19
  EventBus.emit('loginSuccess')
23
- history.push(getRedirect())
20
+ history.push(getRedirect(query))
24
21
  resolve(rs)
25
22
  }).catch(e => {
26
23
  console.error('[Login] 登录失败:', e);
@@ -63,7 +60,7 @@ export default class extends React.Component {
63
60
  submit = values => {
64
61
  this.setState({logging: true})
65
62
  values.password = encodePassword(values.password)
66
- postLogin(values).finally(() => {
63
+ postLogin(values, this.props.location?.query).finally(() => {
67
64
  this.setState({logging: false})
68
65
  })
69
66
  }
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import {Page} from "../../framework";
3
+ import {Button, message, Modal, Space} from "antd";
4
+
5
+ export default class extends React.Component {
6
+
7
+ state = {
8
+ modalOpen:false
9
+ }
10
+
11
+ render() {
12
+ return <Page title="测试组件">
13
+
14
+ <Space>
15
+ <Button type={"primary"} onClick={()=>{message.info('你好,李白!')}} >message.info</Button>
16
+
17
+ <Button danger onClick={()=>{Modal.info({content:'你好,李白!'})}} >modal.info</Button>
18
+
19
+ <Button onClick={()=>{this.setState({modalOpen:true})}} >modal.组件</Button>
20
+
21
+ </Space>
22
+
23
+ <Modal title='modal组件' open={this.state.modalOpen} onCancel={()=>this.setState({modalOpen:false})}>
24
+ 内容内容
25
+ </Modal>
26
+
27
+
28
+ </Page>
29
+ }
30
+ }
@@ -1,50 +1,21 @@
1
1
  import React from "react";
2
2
  import {Button, Form, Input, message} from "antd";
3
- import {history} from 'umi'
4
- import {HttpUtils, PageUtils, GlobalData} from "../framework";
3
+ import {HttpUtils, history} from "../../framework";
5
4
 
6
5
  export default class extends React.Component {
7
6
 
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
7
  onFinish = (values) => {
27
8
  HttpUtils.post('admin/userCenter/update-pwd', values).then(() => {
28
9
  message.success('修改密码成功,请重新登录');
29
- history.push('/login');
10
+ history.push('/public/login');
30
11
  })
31
12
  }
32
13
 
33
14
  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
- })
15
+ return HttpUtils.get("admin/sysUser/pwd-strength", {password: value}, {showError: false})
43
16
  }
44
17
 
45
18
  render() {
46
- if (this.state.checking) return null;
47
-
48
19
  return (
49
20
  <div style={{
50
21
  display: 'flex',