@jiangood/open-admin 3.0.9 → 3.0.11
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/package.json +1 -1
- package/src/framework/components/DownloadModal/index.tsx +3 -0
- package/src/framework/config/index.ts +2 -1
- package/src/framework/config/themeConfig.ts +46 -23
- package/src/layouts/admin/HeaderRight.jsx +3 -1
- package/src/layouts/index.tsx +19 -5
- package/src/pages/system/org/index.jsx +1 -0
package/package.json
CHANGED
|
@@ -142,6 +142,9 @@ export class DownloadModal extends React.Component<DownloadModalProps, ModalStat
|
|
|
142
142
|
}
|
|
143
143
|
filename = parsedName;
|
|
144
144
|
}
|
|
145
|
+
if (filename && filename !== this.state.fileName) {
|
|
146
|
+
this.setState({fileName: filename});
|
|
147
|
+
}
|
|
145
148
|
|
|
146
149
|
const url = window.URL.createObjectURL(new Blob([blob]));
|
|
147
150
|
const link = document.createElement('a');
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { getThemeConfig, getToken } from './themeConfig'
|
|
1
|
+
export { getThemeConfig, getToken, setThemeColors } from './themeConfig'
|
|
2
|
+
export type { ThemeColors } from './themeConfig'
|
|
@@ -3,37 +3,60 @@ import type { ThemeConfig } from 'antd';
|
|
|
3
3
|
|
|
4
4
|
const { getDesignToken } = theme;
|
|
5
5
|
|
|
6
|
+
export interface ThemeColors {
|
|
7
|
+
colorPrimary?: string;
|
|
8
|
+
colorSuccess?: string;
|
|
9
|
+
colorWarning?: string;
|
|
10
|
+
colorError?: string;
|
|
11
|
+
colorBgLayout?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const DEFAULT_COLORS: Required<ThemeColors> = {
|
|
15
|
+
colorPrimary: '#1961AC',
|
|
16
|
+
colorSuccess: '#52c41a',
|
|
17
|
+
colorWarning: '#faad14',
|
|
18
|
+
colorError: '#ff4d4f',
|
|
19
|
+
colorBgLayout: '#f5f5f5',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
let overrideColors: Partial<ThemeColors> | null = null;
|
|
6
23
|
let cachedConfig: ThemeConfig | null = null;
|
|
7
24
|
let cachedToken: Record<string, any> | null = null;
|
|
8
25
|
|
|
9
26
|
function buildConfig(): ThemeConfig {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
const token: Record<string, any> = { borderRadius: 4, ...DEFAULT_COLORS, ...overrideColors };
|
|
28
|
+
const components: Record<string, any> = {
|
|
29
|
+
Layout: { headerBg: 'white', triggerHeight: 32 },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return { token, components };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function syncCssVars(token: Record<string, any>) {
|
|
36
|
+
if (typeof document === 'undefined') return;
|
|
37
|
+
const el = document.documentElement;
|
|
38
|
+
el.style.setProperty('--primary-color', token.colorPrimary);
|
|
39
|
+
el.style.setProperty('--primary-color-hover', token.colorPrimaryHover || token.colorPrimary);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** 由 Layouts 在渲染前调用,传入业务侧颜色覆盖;不传则恢复默认主题 */
|
|
43
|
+
export function setThemeColors(colors?: Partial<ThemeColors>) {
|
|
44
|
+
overrideColors = colors || null;
|
|
45
|
+
cachedConfig = null;
|
|
46
|
+
cachedToken = null;
|
|
47
|
+
syncCssVars(getToken());
|
|
25
48
|
}
|
|
26
49
|
|
|
27
50
|
export function getThemeConfig(): ThemeConfig {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
51
|
+
if (!cachedConfig) {
|
|
52
|
+
cachedConfig = buildConfig();
|
|
53
|
+
}
|
|
54
|
+
return cachedConfig;
|
|
32
55
|
}
|
|
33
56
|
|
|
34
57
|
export function getToken(): Record<string, any> {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
58
|
+
if (!cachedToken) {
|
|
59
|
+
cachedToken = getDesignToken(getThemeConfig());
|
|
60
|
+
}
|
|
61
|
+
return cachedToken;
|
|
39
62
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Avatar, Dropdown, Modal} from "antd";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import {DeviceUtils, HttpUtils, PageUtils, GlobalData, getToken, history, ARTICLE_HEADER_AVATAR_DROPDOWN, ARTICLE_HEADER_RIGHT} from "../../framework";
|
|
3
|
+
import {DeviceUtils, HttpUtils, PageUtils, GlobalData, getToken, history, EventBus, ARTICLE_HEADER_AVATAR_DROPDOWN, ARTICLE_HEADER_RIGHT} from "../../framework";
|
|
4
4
|
|
|
5
5
|
export class HeaderRight extends React.Component {
|
|
6
6
|
|
|
@@ -100,6 +100,7 @@ export class HeaderRight extends React.Component {
|
|
|
100
100
|
onCancel={() => this.setState({alertVisible: false})}
|
|
101
101
|
onOk={() => {
|
|
102
102
|
this.setState({alertVisible: false});
|
|
103
|
+
EventBus.emit('logoutSuccess');
|
|
103
104
|
history.replace('/public/login')
|
|
104
105
|
}}>
|
|
105
106
|
退出登录成功
|
|
@@ -109,6 +110,7 @@ export class HeaderRight extends React.Component {
|
|
|
109
110
|
onOk={() => {
|
|
110
111
|
this.setState({confirmVisible: false});
|
|
111
112
|
localStorage.clear();
|
|
113
|
+
EventBus.emit('logoutSuccess');
|
|
112
114
|
history.replace('/public/login')
|
|
113
115
|
}}>
|
|
114
116
|
退出登录失败,是否清空缓存
|
package/src/layouts/index.tsx
CHANGED
|
@@ -6,20 +6,20 @@ import 'dayjs/locale/zh-cn';
|
|
|
6
6
|
import {history, PageFrame} from "../framework";
|
|
7
7
|
|
|
8
8
|
import AdminLayout from "./admin"
|
|
9
|
-
import {HttpUtils, PageLoading, PageUtils, GlobalData, getThemeConfig, EventBus} from "../framework";
|
|
9
|
+
import {HttpUtils, PageLoading, PageUtils, GlobalData, getThemeConfig, setThemeColors, EventBus} from "../framework";
|
|
10
10
|
import {ErrorBoundary} from "../framework";
|
|
11
|
+
import type {ThemeColors} from "../framework";
|
|
11
12
|
|
|
12
13
|
import '../style/global.less'
|
|
13
14
|
import './index.less'
|
|
14
15
|
|
|
15
16
|
dayjs.locale('zh-cn');
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
+
const baseConfigProps = {
|
|
18
19
|
input: {autoComplete: 'off'},
|
|
19
20
|
form: {validateMessages: {required: '必填项'}, colon: false},
|
|
20
21
|
button: {autoInsertSpace: false},
|
|
21
22
|
locale: zhCN,
|
|
22
|
-
theme: getThemeConfig(),
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export interface HeaderExtraContext {
|
|
@@ -30,6 +30,8 @@ export interface HeaderExtraContext {
|
|
|
30
30
|
interface LayoutsProps {
|
|
31
31
|
headerExtra?: (context: HeaderExtraContext) => React.ReactNode;
|
|
32
32
|
showOrgSwitcher?: (context: HeaderExtraContext) => boolean;
|
|
33
|
+
/** 主题颜色覆盖,不传使用框架默认主题 */
|
|
34
|
+
colors?: Partial<ThemeColors>;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export class Layouts extends React.Component<LayoutsProps> {
|
|
@@ -42,6 +44,12 @@ export class Layouts extends React.Component<LayoutsProps> {
|
|
|
42
44
|
|
|
43
45
|
unlisten: (() => void) | null = null;
|
|
44
46
|
unsubscribeLoginExpired: (() => void) | null = null;
|
|
47
|
+
unsubscribeLogoutSuccess: (() => void) | null = null;
|
|
48
|
+
|
|
49
|
+
constructor(props: LayoutsProps) {
|
|
50
|
+
super(props);
|
|
51
|
+
setThemeColors(props.colors);
|
|
52
|
+
}
|
|
45
53
|
|
|
46
54
|
onLocationChange = ({location}: { location: typeof history.location }) => {
|
|
47
55
|
this.setState({location});
|
|
@@ -101,6 +109,9 @@ export class Layouts extends React.Component<LayoutsProps> {
|
|
|
101
109
|
this.setState({loginExpiredVisible: true});
|
|
102
110
|
}
|
|
103
111
|
});
|
|
112
|
+
this.unsubscribeLogoutSuccess = EventBus.on('logoutSuccess', () => {
|
|
113
|
+
this.setState({loginChecked: false});
|
|
114
|
+
});
|
|
104
115
|
this.loadData();
|
|
105
116
|
}
|
|
106
117
|
|
|
@@ -117,6 +128,9 @@ export class Layouts extends React.Component<LayoutsProps> {
|
|
|
117
128
|
if (this.unsubscribeLoginExpired) {
|
|
118
129
|
this.unsubscribeLoginExpired();
|
|
119
130
|
}
|
|
131
|
+
if (this.unsubscribeLogoutSuccess) {
|
|
132
|
+
this.unsubscribeLogoutSuccess();
|
|
133
|
+
}
|
|
120
134
|
}
|
|
121
135
|
|
|
122
136
|
render() {
|
|
@@ -128,7 +142,7 @@ export class Layouts extends React.Component<LayoutsProps> {
|
|
|
128
142
|
|
|
129
143
|
return (
|
|
130
144
|
<ErrorBoundary minimal>
|
|
131
|
-
<ConfigProvider {...
|
|
145
|
+
<ConfigProvider {...baseConfigProps} theme={getThemeConfig()}>
|
|
132
146
|
{showPageFrame ? <PageFrame url={pathname + search}/> : ready ? <AdminLayout headerExtra={this.props.headerExtra} showOrgSwitcher={this.props.showOrgSwitcher} loginInfo={GlobalData.getLoginInfo()}/> : (
|
|
133
147
|
<PageLoading messages={[
|
|
134
148
|
!siteInfoLoaded && '加载站点信息...',
|
|
@@ -146,7 +160,7 @@ export class Layouts extends React.Component<LayoutsProps> {
|
|
|
146
160
|
<Modal open={this.state.loginExpiredVisible} title="确认操作" okText="确定"
|
|
147
161
|
onCancel={() => this.setState({loginExpiredVisible: false})}
|
|
148
162
|
onOk={() => {
|
|
149
|
-
this.setState({loginExpiredVisible: false});
|
|
163
|
+
this.setState({loginExpiredVisible: false, loginChecked: false});
|
|
150
164
|
PageUtils.redirectToLogin();
|
|
151
165
|
}}>
|
|
152
166
|
登录已过期,请重新登录
|
|
@@ -157,6 +157,7 @@ export default class extends React.Component {
|
|
|
157
157
|
</div>
|
|
158
158
|
{selectedOrg && (
|
|
159
159
|
<Descriptions size='small' column={2}>
|
|
160
|
+
<Descriptions.Item label="唯一标识">{selectedOrg.id}</Descriptions.Item>
|
|
160
161
|
<Descriptions.Item label="名称">{selectedOrg.name}</Descriptions.Item>
|
|
161
162
|
<Descriptions.Item label="类型">{selectedOrg.typeLabel}</Descriptions.Item>
|
|
162
163
|
<Descriptions.Item label="上级机构">{selectedOrg.parentName || '-'}</Descriptions.Item>
|