@jiangood/open-admin 2.0.0 → 2.2.4
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/config/config.js +9 -22
- package/package.json +5 -1
- package/src/.umi-production/appData.json +67 -108
- package/src/.umi-production/core/route.tsx +1 -2
- package/src/.umi-production/umi.ts +2 -2
- package/src/framework/components/Gap/index.tsx +37 -41
- package/src/framework/components/Page/index.less +1 -1
- package/src/framework/components/Page/index.tsx +19 -22
- package/src/framework/components/ViewRange/index.tsx +12 -17
- package/src/framework/components/system/ButtonList.tsx +12 -32
- package/src/framework/fields/FieldEditor/index.tsx +3 -2
- package/src/framework/fields/FieldUploadFile/index.tsx +8 -4
- package/src/framework/utils/MessageUtils.tsx +21 -99
- package/src/framework/utils/system/HttpUtils.ts +2 -1
- package/src/framework/utils/system/SysUtils.ts +8 -0
- package/src/layouts/PageRender.d.ts +2 -17
- package/src/layouts/PageRender.jsx +14 -76
- package/src/layouts/admin/TabPageRender.jsx +138 -158
- package/src/layouts/admin/index.jsx +120 -17
- package/src/layouts/admin/index.less +123 -5
- package/src/layouts/index.jsx +78 -161
- package/src/loading.jsx +17 -16
- package/src/pages/404.jsx +7 -5
- package/src/pages/about.jsx +3 -3
- package/src/pages/index.jsx +4 -5
- package/src/pages/login.jsx +16 -9
- package/src/pages/login.less +0 -1
- package/src/pages/system/dict/index.jsx +7 -10
- package/src/pages/system/file/index.jsx +5 -5
- package/src/pages/system/job/index.jsx +9 -7
- package/src/pages/system/log/index.jsx +4 -5
- package/src/pages/system/manual/index.jsx +6 -4
- package/src/pages/system/org/index.jsx +4 -2
- package/src/pages/system/role/index.jsx +9 -7
- package/src/pages/system/role/perm.jsx +3 -4
- package/src/pages/system/user/index.jsx +8 -6
- package/src/pages/userCenter/index.jsx +1 -1
- package/src/pages/userCenter/message.jsx +4 -2
- package/src/pages/system/api/index.jsx +0 -279
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
.main-layout {
|
|
2
|
-
|
|
2
|
+
height: 100vh;
|
|
3
|
+
overflow: hidden;
|
|
3
4
|
.header {
|
|
4
5
|
padding: 0 20px;
|
|
5
6
|
height: 48px;
|
|
6
7
|
display: flex;
|
|
7
|
-
justify-content: space-between;
|
|
8
8
|
align-items: center;
|
|
9
9
|
border-bottom: 1px solid rgb(233, 237, 240);
|
|
10
10
|
background-color: rgb(246, 248, 250);
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
display: flex;
|
|
15
15
|
align-items: center;
|
|
16
16
|
gap: 8px;
|
|
17
|
+
flex-shrink: 0;
|
|
17
18
|
|
|
18
19
|
.logo-img {
|
|
19
20
|
height: 38px;
|
|
@@ -21,10 +22,41 @@
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
.top-nav {
|
|
26
|
+
flex: 1;
|
|
27
|
+
display: flex;
|
|
28
|
+
align-items: center;
|
|
29
|
+
margin: 0 16px;
|
|
30
|
+
height: 100%;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
|
|
33
|
+
.top-nav-item {
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
gap: 4px;
|
|
37
|
+
padding: 0 16px;
|
|
38
|
+
height: 100%;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
color: rgba(0, 0, 0, 0.65);
|
|
41
|
+
transition: color 0.2s;
|
|
42
|
+
white-space: nowrap;
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
color: #1961AC;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&.active {
|
|
49
|
+
color: #1961AC;
|
|
50
|
+
box-shadow: inset 0 -2px 0 #1961AC;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
24
55
|
.header-right {
|
|
25
56
|
line-height: 36px;
|
|
26
57
|
display: flex;
|
|
27
58
|
align-items: center;
|
|
59
|
+
flex-shrink: 0;
|
|
28
60
|
|
|
29
61
|
.item {
|
|
30
62
|
padding: 0 0.5rem;
|
|
@@ -59,10 +91,96 @@
|
|
|
59
91
|
}
|
|
60
92
|
|
|
61
93
|
#admin-layout-content {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
overflow: hidden;
|
|
97
|
+
|
|
98
|
+
.oa-tabs {
|
|
99
|
+
flex: 1;
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
|
|
104
|
+
.oa-tab-bar {
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-wrap: nowrap;
|
|
107
|
+
overflow-x: auto;
|
|
108
|
+
overflow-y: hidden;
|
|
109
|
+
flex-shrink: 0;
|
|
110
|
+
margin-bottom: 0;
|
|
111
|
+
border-bottom: 1px solid #e8e8e8;
|
|
112
|
+
background: #fff;
|
|
113
|
+
|
|
114
|
+
&::-webkit-scrollbar {
|
|
115
|
+
height: 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.oa-tab {
|
|
120
|
+
display: inline-flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 4px;
|
|
123
|
+
padding: 0 12px;
|
|
124
|
+
height: 32px;
|
|
125
|
+
line-height: 32px;
|
|
126
|
+
font-size: 13px;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
border-right: 1px solid #e8e8e8;
|
|
129
|
+
white-space: nowrap;
|
|
130
|
+
color: rgba(0, 0, 0, 0.65);
|
|
131
|
+
background: #fafafa;
|
|
132
|
+
transition: color 0.2s, background 0.2s;
|
|
133
|
+
position: relative;
|
|
134
|
+
flex-shrink: 0;
|
|
135
|
+
|
|
136
|
+
&:hover {
|
|
137
|
+
color: #1961AC;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&.active {
|
|
141
|
+
color: #1961AC;
|
|
142
|
+
background: #fff;
|
|
143
|
+
font-weight: 500;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.oa-tab-label {
|
|
147
|
+
max-width: 120px;
|
|
148
|
+
overflow: hidden;
|
|
149
|
+
text-overflow: ellipsis;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.oa-tab-close {
|
|
153
|
+
display: inline-flex;
|
|
154
|
+
align-items: center;
|
|
155
|
+
justify-content: center;
|
|
156
|
+
width: 16px;
|
|
157
|
+
height: 16px;
|
|
158
|
+
font-size: 12px;
|
|
159
|
+
line-height: 1;
|
|
160
|
+
border-radius: 50%;
|
|
161
|
+
color: rgba(0, 0, 0, 0.45);
|
|
162
|
+
|
|
163
|
+
&:hover {
|
|
164
|
+
background: rgba(0, 0, 0, 0.08);
|
|
165
|
+
color: rgba(0, 0, 0, 0.88);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.oa-tabs-content {
|
|
171
|
+
flex: 1;
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
|
|
174
|
+
.oa-tab-pane {
|
|
175
|
+
height: 100%;
|
|
176
|
+
}
|
|
65
177
|
}
|
|
66
178
|
}
|
|
67
179
|
}
|
|
68
180
|
}
|
|
181
|
+
|
|
182
|
+
@media (max-width: 768px) {
|
|
183
|
+
.top-nav {
|
|
184
|
+
display: none !important;
|
|
185
|
+
}
|
|
186
|
+
}
|
package/src/layouts/index.jsx
CHANGED
|
@@ -1,185 +1,102 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import {ConfigProvider} from "antd";
|
|
1
|
+
import React, {useState, useEffect, useRef} from "react";
|
|
2
|
+
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,
|
|
6
|
+
import {Outlet, useLocation} from "umi";
|
|
7
7
|
|
|
8
8
|
import AdminLayout from "./admin"
|
|
9
|
-
import {
|
|
10
|
-
ArrayUtils,
|
|
11
|
-
HttpUtils,
|
|
12
|
-
MessageHolder,
|
|
13
|
-
PageLoading,
|
|
14
|
-
PageUtils, StringUtils,
|
|
15
|
-
SysUtils,
|
|
16
|
-
ThemeUtils,
|
|
17
|
-
} from "../framework";
|
|
18
|
-
import {Logger} from "../framework/utils/Logger";
|
|
9
|
+
import {HttpUtils, PageLoading, PageUtils, SysUtils, ThemeUtils} from "../framework";
|
|
19
10
|
|
|
20
11
|
import '../style/global.less'
|
|
21
12
|
import './index.less'
|
|
22
13
|
|
|
23
14
|
dayjs.locale('zh-cn');
|
|
24
15
|
|
|
25
|
-
//
|
|
26
|
-
const
|
|
16
|
+
// 不需要登录和布局的页面
|
|
17
|
+
const PUBLIC_PAGES = ['/login', '/test']
|
|
27
18
|
|
|
28
|
-
function
|
|
29
|
-
if(pathname === '/' || pathname === '/index')
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return true
|
|
35
|
-
}
|
|
36
|
-
return ArrayUtils.contains(SIMPLE_URLS, pathname) ;
|
|
19
|
+
function isPublicPage(pathname, search) {
|
|
20
|
+
if (pathname === '/' || pathname === '/index') return false;
|
|
21
|
+
if (pathname.startsWith("/test/")) return true;
|
|
22
|
+
if (PUBLIC_PAGES.includes(pathname)) return true;
|
|
23
|
+
if (search && new URLSearchParams(search).has('_noLayout')) return true;
|
|
24
|
+
return false;
|
|
37
25
|
}
|
|
38
26
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
27
|
+
const configProps = {
|
|
28
|
+
input: {autoComplete: 'off'},
|
|
29
|
+
form: {validateMessages: {required: '必填项'}, colon: false},
|
|
30
|
+
button: {autoInsertSpace: false},
|
|
31
|
+
locale: zhCN,
|
|
32
|
+
theme: {
|
|
33
|
+
token: {
|
|
34
|
+
colorPrimary: ThemeUtils.getColor("primary-color"),
|
|
35
|
+
colorSuccess: ThemeUtils.getColor("success-color"),
|
|
36
|
+
colorWarning: ThemeUtils.getColor("warning-color"),
|
|
37
|
+
colorError: ThemeUtils.getColor("error-color"),
|
|
38
|
+
borderRadius: 4,
|
|
39
|
+
},
|
|
40
|
+
components: {
|
|
41
|
+
Menu: {
|
|
42
|
+
darkItemBg: ThemeUtils.getColor("primary-color"),
|
|
43
|
+
darkPopupBg: ThemeUtils.getColor("primary-color"),
|
|
44
|
+
darkItemSelectedBg: ThemeUtils.getColor("primary-color-click"),
|
|
45
|
+
darkItemHoverBg: ThemeUtils.getColor("primary-color-hover"),
|
|
46
|
+
darkSubMenuItemBg: ThemeUtils.getColor("primary-color"),
|
|
47
|
+
},
|
|
48
|
+
Layout: {
|
|
49
|
+
siderBg: ThemeUtils.getColor("primary-color"),
|
|
50
|
+
triggerBg: ThemeUtils.getColor("primary-color-click"),
|
|
51
|
+
headerBg: 'white',
|
|
52
|
+
triggerHeight: 32,
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function initApp() {
|
|
59
|
+
return Promise.all([
|
|
60
|
+
HttpUtils.get("/admin/public/site-info"),
|
|
61
|
+
HttpUtils.get('/admin/public/check-login'),
|
|
62
|
+
]).then(([siteInfo, loginRs]) => {
|
|
63
|
+
SysUtils.setSiteInfo(siteInfo);
|
|
64
|
+
const {needUpdatePwd, dictInfo, loginInfo} = loginRs;
|
|
65
|
+
SysUtils.setDictInfo(dictInfo);
|
|
66
|
+
SysUtils.setLoginInfo(loginInfo);
|
|
67
|
+
if (needUpdatePwd) {
|
|
68
|
+
PageUtils.open('/userCenter/ChangePassword', '修改密码');
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
}).catch(() => {
|
|
73
|
+
PageUtils.redirectToLogin();
|
|
74
|
+
return false;
|
|
75
|
+
});
|
|
44
76
|
}
|
|
45
77
|
|
|
46
|
-
|
|
78
|
+
export function Layouts() {
|
|
79
|
+
const {pathname, search} = useLocation();
|
|
80
|
+
const [ready, setReady] = useState(false);
|
|
81
|
+
const loadedRef = useRef(false);
|
|
47
82
|
|
|
48
|
-
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (isPublicPage(pathname)) return;
|
|
85
|
+
if (loadedRef.current) return;
|
|
86
|
+
loadedRef.current = true;
|
|
87
|
+
initApp().then(ok => { if (ok) setReady(true); });
|
|
88
|
+
}, [pathname]);
|
|
49
89
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
siteInfoLoading: true,
|
|
53
|
-
loginInfoFinish: false
|
|
90
|
+
if (isPublicPage(pathname, search)) {
|
|
91
|
+
return <ConfigProvider {...configProps}><App><Outlet/></App></ConfigProvider>;
|
|
54
92
|
}
|
|
55
93
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
this.setState({messageHolderInit:true});
|
|
94
|
+
if (!ready) {
|
|
95
|
+
return <ConfigProvider {...configProps}><App><PageLoading message='加载中...'/></App></ConfigProvider>;
|
|
59
96
|
}
|
|
60
97
|
|
|
61
|
-
|
|
62
|
-
loadSiteInfo = () => {
|
|
63
|
-
HttpUtils.get("/admin/public/site-info").then(rs => {
|
|
64
|
-
SysUtils.setSiteInfo(rs)
|
|
65
|
-
this.setState({siteInfoLoading: false})
|
|
66
|
-
this.loadLoginInfo()
|
|
67
|
-
})
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
componentDidUpdate(prevProps, prevState, snapshot) {
|
|
71
|
-
const pre = prevProps.location.pathname
|
|
72
|
-
const cur = this.props.location.pathname
|
|
73
|
-
if (pre !== cur) {
|
|
74
|
-
this.loadLoginInfo()
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
loadLoginInfo = () => {
|
|
81
|
-
const {pathname} = this.props.location;
|
|
82
|
-
if (checkIsPurePage(pathname) || checkIsSimplePage(pathname) || this.state.loginInfoFinish) {
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
HttpUtils.get('/admin/public/check-login')
|
|
87
|
-
.then(rs => {
|
|
88
|
-
const {needUpdatePwd, dictInfo, loginInfo} = rs
|
|
89
|
-
SysUtils.setDictInfo(dictInfo)
|
|
90
|
-
SysUtils.setLoginInfo(loginInfo)
|
|
91
|
-
if (!needUpdatePwd) {
|
|
92
|
-
this.setState({loginInfoFinish: true});
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (needUpdatePwd) {
|
|
97
|
-
PageUtils.open('/userCenter/ChangePassword', '修改密码')
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
.catch(async () => {
|
|
102
|
-
PageUtils.redirectToLogin()
|
|
103
|
-
})
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
render() {
|
|
107
|
-
return <ConfigProvider
|
|
108
|
-
input={{autoComplete: 'off'}}
|
|
109
|
-
form={{
|
|
110
|
-
validateMessages: {
|
|
111
|
-
required: '必填项'
|
|
112
|
-
}, colon: false
|
|
113
|
-
}}
|
|
114
|
-
button={{
|
|
115
|
-
autoInsertSpace: false
|
|
116
|
-
}}
|
|
117
|
-
locale={zhCN}
|
|
118
|
-
theme={{
|
|
119
|
-
token: {
|
|
120
|
-
colorPrimary: ThemeUtils.getColor("primary-color"),
|
|
121
|
-
colorSuccess: ThemeUtils.getColor("success-color"),
|
|
122
|
-
colorWarning: ThemeUtils.getColor("warning-color"),
|
|
123
|
-
colorError: ThemeUtils.getColor("error-color"),
|
|
124
|
-
borderRadius: 4,
|
|
125
|
-
},
|
|
126
|
-
components: {
|
|
127
|
-
Menu: {
|
|
128
|
-
darkItemBg: ThemeUtils.getColor("primary-color"),
|
|
129
|
-
darkPopupBg: ThemeUtils.getColor("primary-color"),
|
|
130
|
-
darkItemSelectedBg: ThemeUtils.getColor("primary-color-click"),
|
|
131
|
-
darkItemHoverBg: ThemeUtils.getColor("primary-color-hover"),
|
|
132
|
-
darkSubMenuItemBg: ThemeUtils.getColor("primary-color")
|
|
133
|
-
},
|
|
134
|
-
Layout: {
|
|
135
|
-
siderBg: ThemeUtils.getColor("primary-color"),
|
|
136
|
-
triggerBg: ThemeUtils.getColor("primary-color-click"),
|
|
137
|
-
headerBg: 'white',
|
|
138
|
-
triggerHeight: 32
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}}>
|
|
142
|
-
|
|
143
|
-
<MessageHolder onFinish={this.onMessageHolderFinish} />
|
|
144
|
-
{this.renderContent()}
|
|
145
|
-
</ConfigProvider>
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
renderContent = () => {
|
|
150
|
-
const {pathname} = this.props.location;
|
|
151
|
-
|
|
152
|
-
if(checkIsPurePage(pathname)){
|
|
153
|
-
return <Outlet/>
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
if(!this.state.messageHolderInit) {
|
|
157
|
-
this.log.info('加载message holder...')
|
|
158
|
-
return <PageLoading message='加载消息组件...'/>
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const {params = {}} = this.props.location;
|
|
162
|
-
if (checkIsSimplePage(pathname) || params.hasOwnProperty('_noLayout')) {
|
|
163
|
-
return <Outlet/>
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (this.state.siteInfoLoading) {
|
|
169
|
-
return <PageLoading message='加载站点信息...'/>
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (!this.state.loginInfoFinish) {
|
|
175
|
-
return <PageLoading message='加载登录信息...'/>
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return <AdminLayout path={this.state.path} logo={this.props.logo}/>
|
|
179
|
-
};
|
|
98
|
+
return <ConfigProvider {...configProps}><App><AdminLayout/></App></ConfigProvider>;
|
|
180
99
|
}
|
|
181
100
|
|
|
182
|
-
|
|
183
|
-
export
|
|
184
|
-
export default Layouts
|
|
185
|
-
export * from './PageRender'
|
|
101
|
+
export default Layouts;
|
|
102
|
+
export * from './PageRender'
|
package/src/loading.jsx
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {Spin} from "antd";
|
|
3
|
-
import {ThemeUtils} from "./framework";
|
|
2
|
+
import { Spin } from "antd";
|
|
3
|
+
import { ThemeUtils } from "./framework";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
const Loading = () => (
|
|
6
|
+
<div
|
|
7
|
+
style={{
|
|
8
|
+
display: 'flex',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
height: '100vh',
|
|
12
|
+
background: ThemeUtils.getColor("background-color")
|
|
13
|
+
}}
|
|
14
|
+
>
|
|
15
|
+
<Spin size='large' />
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
export default Loading;
|
package/src/pages/404.jsx
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import {Result} from "antd";
|
|
3
|
+
import {Page} from "../framework";
|
|
3
4
|
|
|
4
5
|
export default class extends React.Component {
|
|
5
6
|
|
|
6
7
|
render() {
|
|
7
|
-
return <
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
return <Page>
|
|
9
|
+
<Result
|
|
10
|
+
status={404}
|
|
11
|
+
title='页面不存在'
|
|
12
|
+
/>
|
|
13
|
+
</Page>
|
|
12
14
|
}
|
|
13
15
|
}
|
package/src/pages/about.jsx
CHANGED
package/src/pages/index.jsx
CHANGED
package/src/pages/login.jsx
CHANGED
|
@@ -38,14 +38,19 @@ export default class extends React.Component {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
async componentDidMount() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
const siteInfo = SysUtils.getSiteInfo()
|
|
42
|
+
if (siteInfo && siteInfo.rsaPublicKey) {
|
|
43
|
+
this.setState({siteInfo})
|
|
44
44
|
return
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// localStorage 中无站点信息,从服务端重新加载
|
|
47
|
+
try {
|
|
48
|
+
const rs = await HttpUtils.get('/admin/public/site-info')
|
|
49
|
+
SysUtils.setSiteInfo(rs)
|
|
50
|
+
this.setState({siteInfo: rs})
|
|
51
|
+
} catch (e) {
|
|
52
|
+
message.error('加载站点信息失败,请刷新页面重试')
|
|
53
|
+
}
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
submit = values => {
|
|
@@ -69,9 +74,11 @@ export default class extends React.Component {
|
|
|
69
74
|
render() {
|
|
70
75
|
const {siteInfo} = this.state
|
|
71
76
|
|
|
72
|
-
const pageStyle = {
|
|
77
|
+
const pageStyle = {
|
|
78
|
+
backgroundImage: `url("${SysUtils.contextPath('/admin/public/login_bg.jpg')}")`
|
|
79
|
+
}
|
|
73
80
|
if (siteInfo.loginBackground) {
|
|
74
|
-
const url = 'admin/sysFile/preview/' + siteInfo.loginBackground;
|
|
81
|
+
const url = SysUtils.contextPath('/admin/sysFile/preview/' + siteInfo.loginBackground);
|
|
75
82
|
pageStyle.backgroundImage = 'url("' + url + '")'
|
|
76
83
|
}
|
|
77
84
|
|
|
@@ -110,7 +117,7 @@ export default class extends React.Component {
|
|
|
110
117
|
<Space style={{alignItems: 'center'}}>
|
|
111
118
|
<Input size='large' placeholder='验证码' prefix={<SafetyCertificateOutlined/>}/>
|
|
112
119
|
<img height={36} width={100}
|
|
113
|
-
src={"/admin/auth/captcha-image?_random=" + this.state.random}
|
|
120
|
+
src={SysUtils.contextPath("/admin/auth/captcha-image?_random=" + this.state.random)}
|
|
114
121
|
onClick={() => this.setState({random: Math.random()})}/>
|
|
115
122
|
</Space>
|
|
116
123
|
</Form.Item>
|
package/src/pages/login.less
CHANGED
|
@@ -33,7 +33,9 @@ export default class extends React.Component {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
onFinish = values => {
|
|
36
|
-
|
|
36
|
+
const isNew = !values.id;
|
|
37
|
+
const url = isNew ? 'admin/dict/create' : 'admin/dict/update';
|
|
38
|
+
HttpUtils.post(url, values).then(rs => {
|
|
37
39
|
this.setState({formOpen: false})
|
|
38
40
|
this.tableRef.current.reload()
|
|
39
41
|
})
|
|
@@ -90,15 +92,11 @@ export default class extends React.Component {
|
|
|
90
92
|
title: '操作',
|
|
91
93
|
dataIndex: 'option',
|
|
92
94
|
render: (_, record) => {
|
|
93
|
-
if(!record.id){ // 非数据库定义的不让修改
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
95
|
return (
|
|
98
96
|
<ButtonList>
|
|
99
|
-
<Button size='small' perm='
|
|
97
|
+
<Button size='small' perm='sys-dict:update'
|
|
100
98
|
onClick={() => this.handleEdit(record)}> 编辑 </Button>
|
|
101
|
-
<Popconfirm perm='
|
|
99
|
+
<Popconfirm perm='sys-dict:delete' title='是否确定删除字典项'
|
|
102
100
|
onConfirm={() => this.handleDelete(record)}>
|
|
103
101
|
<Button size='small'>删除</Button>
|
|
104
102
|
</Popconfirm>
|
|
@@ -109,13 +107,13 @@ export default class extends React.Component {
|
|
|
109
107
|
]
|
|
110
108
|
|
|
111
109
|
render() {
|
|
112
|
-
return <Page
|
|
110
|
+
return <Page>
|
|
113
111
|
<ProTable
|
|
114
112
|
rowKey='uid'
|
|
115
113
|
actionRef={this.tableRef}
|
|
116
114
|
toolBarRender={() => {
|
|
117
115
|
return <ButtonList>
|
|
118
|
-
<Button perm='
|
|
116
|
+
<Button perm='sys-dict:create' type='primary' onClick={this.handleAdd} >
|
|
119
117
|
<PlusOutlined/> 新增
|
|
120
118
|
</Button>
|
|
121
119
|
</ButtonList>
|
|
@@ -126,7 +124,6 @@ export default class extends React.Component {
|
|
|
126
124
|
}}
|
|
127
125
|
columns={this.columns}
|
|
128
126
|
showToolbarSearch={true}
|
|
129
|
-
scrollY={500}
|
|
130
127
|
/>
|
|
131
128
|
<Modal
|
|
132
129
|
title='编辑数据字典项'
|
|
@@ -2,7 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import {Button, Form, Input, Modal, Popconfirm} from 'antd'
|
|
3
3
|
import {CloudUploadOutlined} from "@ant-design/icons";
|
|
4
4
|
|
|
5
|
-
import {ButtonList, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpUtils, ProTable} from "../../../framework";
|
|
5
|
+
import {ButtonList, FieldDateRange, FieldDictSelect, FieldUploadFile, HttpUtils, Page, ProTable, SysUtils} from "../../../framework";
|
|
6
6
|
|
|
7
7
|
export default class extends React.Component {
|
|
8
8
|
|
|
@@ -59,7 +59,7 @@ export default class extends React.Component {
|
|
|
59
59
|
title: '预览',
|
|
60
60
|
dataIndex: 'id',
|
|
61
61
|
render(id, record) {
|
|
62
|
-
const nodes = [<a href={'/admin/sysFile/preview/' + record.id} target='_blank'>预览</a>]
|
|
62
|
+
const nodes = [<a href={SysUtils.contextPath('/admin/sysFile/preview/' + record.id)} target='_blank'>预览</a>]
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
if (record.imageUrls?.length > 0) {
|
|
@@ -79,7 +79,7 @@ export default class extends React.Component {
|
|
|
79
79
|
dataIndex: 'option',
|
|
80
80
|
render: (_, record) => (
|
|
81
81
|
<ButtonList>
|
|
82
|
-
<Popconfirm perm='
|
|
82
|
+
<Popconfirm perm='sys-file:delete' title='是否确定删除文件信息'
|
|
83
83
|
onConfirm={() => this.handleDelete(record)}>
|
|
84
84
|
<a>删除</a>
|
|
85
85
|
</Popconfirm>
|
|
@@ -89,7 +89,7 @@ export default class extends React.Component {
|
|
|
89
89
|
]
|
|
90
90
|
|
|
91
91
|
render() {
|
|
92
|
-
return
|
|
92
|
+
return <Page>
|
|
93
93
|
<ProTable
|
|
94
94
|
actionRef={this.tableRef}
|
|
95
95
|
toolBarRender={() => {
|
|
@@ -140,7 +140,7 @@ export default class extends React.Component {
|
|
|
140
140
|
</Form>
|
|
141
141
|
</Modal>
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
</Page>
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
|