@jiangood/open-admin 3.0.11 → 3.0.13
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 +3 -2
- package/src/framework/components/DownloadModal/index.tsx +1 -2
- package/src/framework/components/ProTable/index.tsx +3 -1
- package/src/framework/fields/FieldEditor/index.tsx +56 -10
- package/src/framework/fields/FieldUploadFile/index.tsx +7 -24
- package/src/framework/fields/FieldUploadImage/index.tsx +595 -0
- package/src/framework/fields/index.ts +1 -0
- package/src/framework/views/ViewImage/index.tsx +56 -46
- package/src/layouts/admin/index.less +1 -1
- package/src/layouts/index.tsx +1 -0
- package/src/pages/article/$code.jsx +20 -6
- package/src/pages/article/article.less +124 -0
- package/src/pages/system/article/index.jsx +14 -24
- package/src/pages/system/file/index.jsx +101 -55
- package/src/pages/system/job/index.jsx +16 -16
- package/src/pages/userCenter/index.jsx +1 -9
package/package.json
CHANGED
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
"@ant-design/icons": "^6.0.0",
|
|
15
15
|
"@tinymce/tinymce-react": "^6.0.0",
|
|
16
16
|
"antd": "^6.0.0",
|
|
17
|
-
"antd-img-crop": "^4.23.0",
|
|
18
17
|
"axios": "^1.13.2",
|
|
18
|
+
"compressorjs": "^1.2.1",
|
|
19
|
+
"cropperjs": "^1.6.2",
|
|
19
20
|
"dayjs": "^1.11.13",
|
|
20
21
|
"lodash": "^4.17.23",
|
|
21
22
|
"qs": "^6.14.0",
|
|
@@ -48,5 +49,5 @@
|
|
|
48
49
|
"test:e2e": "playwright test",
|
|
49
50
|
"test:e2e:ui": "playwright test --ui"
|
|
50
51
|
},
|
|
51
|
-
"version": "3.0.
|
|
52
|
+
"version": "3.0.13"
|
|
52
53
|
}
|
|
@@ -281,8 +281,7 @@ export class DownloadModal extends React.Component<DownloadModalProps, ModalStat
|
|
|
281
281
|
<div style={{padding: '20px 0'}}>
|
|
282
282
|
{/* 文件名 */}
|
|
283
283
|
<div style={{marginBottom: 16, fontSize: 15, fontWeight: 500, color: '#333'}}>
|
|
284
|
-
|
|
285
|
-
{fileName || '未知文件'}
|
|
284
|
+
文件名:{fileName || '未知文件'}
|
|
286
285
|
</div>
|
|
287
286
|
|
|
288
287
|
{/* 下载中 */}
|
|
@@ -9,6 +9,7 @@ import './index.less'
|
|
|
9
9
|
/** 通过 actionRef 暴露的表格操作 */
|
|
10
10
|
export interface ProTableActionRef {
|
|
11
11
|
reload: () => void;
|
|
12
|
+
clearSelection: () => void;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/** request 返回结构(Spring Data Page 序列化 + 扩展数据) */
|
|
@@ -122,7 +123,8 @@ export class ProTable<T = any> extends React.Component<ProTableProps<T>, ProTabl
|
|
|
122
123
|
this.loadData()
|
|
123
124
|
if (this.props.actionRef) {
|
|
124
125
|
this.props.actionRef.current = {
|
|
125
|
-
reload: () => this.loadData()
|
|
126
|
+
reload: () => this.loadData(),
|
|
127
|
+
clearSelection: () => this.setState({selectedRowKeys: [], selectedRows: []})
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {Spin} from 'antd';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import {Editor as TinyMceEditor} from '@tinymce/tinymce-react';
|
|
3
4
|
import {UrlUtils} from '../../utils';
|
|
@@ -6,8 +7,8 @@ import type {FieldProps} from '../types';
|
|
|
6
7
|
export interface FieldEditorProps extends FieldProps<string> {
|
|
7
8
|
/** 编辑器高度,默认 300 */
|
|
8
9
|
height?: number;
|
|
9
|
-
/**
|
|
10
|
-
|
|
10
|
+
/** 是否公开免登录访问,默认 true(富文本图片需公开访问) */
|
|
11
|
+
isPublic?: boolean;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
@@ -15,18 +16,42 @@ export interface FieldEditorProps extends FieldProps<string> {
|
|
|
15
16
|
*
|
|
16
17
|
* 图片上传相关配置 https://www.tiny.cloud/docs/tinymce/7/image/
|
|
17
18
|
*/
|
|
18
|
-
export class FieldEditor extends React.Component<FieldEditorProps> {
|
|
19
|
+
export class FieldEditor extends React.Component<FieldEditorProps, {loading: boolean}> {
|
|
20
|
+
state = {loading: false};
|
|
21
|
+
private timer: number | undefined;
|
|
22
|
+
|
|
23
|
+
componentDidMount() {
|
|
24
|
+
this.timer = window.setTimeout(() => {
|
|
25
|
+
this.setState({loading: true});
|
|
26
|
+
}, 200);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
componentWillUnmount() {
|
|
30
|
+
if (this.timer != null) {
|
|
31
|
+
window.clearTimeout(this.timer);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
19
35
|
render() {
|
|
20
|
-
const
|
|
21
|
-
const
|
|
36
|
+
const {loading} = this.state;
|
|
37
|
+
const isPublic = this.props.isPublic ?? true;
|
|
38
|
+
const uploadUrl = UrlUtils.contextPath('/admin/sysFile/upload') + '?isPublic=' + isPublic;
|
|
22
39
|
const jsUrl = UrlUtils.contextPath('/admin/tinymce/tinymce.min.js');
|
|
23
40
|
const {value, onChange, height} = this.props;
|
|
41
|
+
const editorHeight = height || 300;
|
|
24
42
|
|
|
25
43
|
return (
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
44
|
+
<div style={{position: 'relative', minHeight: loading ? editorHeight + 44 : undefined}}>
|
|
45
|
+
<TinyMceEditor
|
|
46
|
+
value={value}
|
|
47
|
+
tinymceScriptSrc={jsUrl}
|
|
48
|
+
onInit={() => {
|
|
49
|
+
if (this.timer != null) {
|
|
50
|
+
window.clearTimeout(this.timer);
|
|
51
|
+
}
|
|
52
|
+
this.setState({loading: false});
|
|
53
|
+
}}
|
|
54
|
+
init={{
|
|
30
55
|
min_height: 300,
|
|
31
56
|
language: 'zh_CN',
|
|
32
57
|
height: height,
|
|
@@ -54,7 +79,28 @@ export class FieldEditor extends React.Component<FieldEditorProps> {
|
|
|
54
79
|
onChange(content);
|
|
55
80
|
}
|
|
56
81
|
}}
|
|
57
|
-
|
|
82
|
+
/>
|
|
83
|
+
{loading && (
|
|
84
|
+
<div style={{
|
|
85
|
+
position: 'absolute',
|
|
86
|
+
top: 0,
|
|
87
|
+
left: 0,
|
|
88
|
+
right: 0,
|
|
89
|
+
bottom: 0,
|
|
90
|
+
minHeight: editorHeight + 44,
|
|
91
|
+
display: 'flex',
|
|
92
|
+
flexDirection: 'column',
|
|
93
|
+
alignItems: 'center',
|
|
94
|
+
justifyContent: 'center',
|
|
95
|
+
gap: 8,
|
|
96
|
+
background: '#fff',
|
|
97
|
+
zIndex: 1,
|
|
98
|
+
}}>
|
|
99
|
+
<Spin/>
|
|
100
|
+
<span style={{color: '#999'}}>编辑器加载中...</span>
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
58
104
|
);
|
|
59
105
|
}
|
|
60
106
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import ImgCrop from "antd-img-crop";
|
|
3
|
-
import type {ImgCropProps} from "antd-img-crop";
|
|
4
2
|
import {message, Modal, Upload} from "antd";
|
|
5
3
|
import type {UploadChangeParam, UploadFile, UploadProps} from "antd";
|
|
6
4
|
import { UploadOutlined } from "@ant-design/icons";
|
|
@@ -14,42 +12,34 @@ export type SysUploadFile = UploadFile & { objectName?: string };
|
|
|
14
12
|
export interface FieldUploadFileProps extends FieldProps<string> {
|
|
15
13
|
/** 最大上传数量,默认 1 */
|
|
16
14
|
maxCount?: number;
|
|
17
|
-
/** 是否启用上传前裁切图片 */
|
|
18
|
-
cropImage?: boolean;
|
|
19
|
-
/** 裁切配置(antd-img-crop 的 cropperProps) */
|
|
20
|
-
cropperProps?: ImgCropProps['cropperProps'];
|
|
21
15
|
/** 上传列表的内建样式,默认 picture-card */
|
|
22
16
|
listType?: UploadProps['listType'];
|
|
23
17
|
/** 接受的文件类型,如 image/* */
|
|
24
18
|
accept?: string;
|
|
25
|
-
/**
|
|
26
|
-
|
|
19
|
+
/** 是否公开免登录访问,默认 true(private 需登录) */
|
|
20
|
+
isPublic?: boolean;
|
|
27
21
|
/** 文件列表变化回调(新增文件上传成功后才触发) */
|
|
28
22
|
onFileChange?: (fileList: SysUploadFile[]) => void;
|
|
29
23
|
}
|
|
30
24
|
|
|
31
25
|
interface FieldUploadFileState {
|
|
32
26
|
maxCount: number;
|
|
33
|
-
cropImage: boolean;
|
|
34
27
|
fileList: SysUploadFile[];
|
|
35
28
|
/** 逗号分隔的文件 objectName */
|
|
36
29
|
value: string | null;
|
|
37
30
|
accept?: string;
|
|
38
|
-
|
|
31
|
+
isPublic?: boolean;
|
|
39
32
|
}
|
|
40
33
|
|
|
41
34
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* 可参考 react-easy-crop
|
|
35
|
+
* 通用文件上传(不含图片压缩/裁切,图片上传请使用 FieldUploadImage)
|
|
45
36
|
*/
|
|
46
37
|
export class FieldUploadFile extends React.Component<FieldUploadFileProps, FieldUploadFileState & { errorTitle?: string; errorContent?: string; previewObjectName?: string }> {
|
|
47
38
|
|
|
48
39
|
state: FieldUploadFileState & { errorTitle?: string; errorContent?: string; previewObjectName?: string } = {
|
|
49
40
|
// 传入的参数
|
|
50
41
|
maxCount: 1,
|
|
51
|
-
|
|
52
|
-
visibility: 'public',
|
|
42
|
+
isPublic: true,
|
|
53
43
|
|
|
54
44
|
// 内部参数
|
|
55
45
|
fileList: [],
|
|
@@ -65,8 +55,7 @@ export class FieldUploadFile extends React.Component<FieldUploadFileProps, Field
|
|
|
65
55
|
componentDidUpdate(prevProps: FieldUploadFileProps) {
|
|
66
56
|
const next: Partial<FieldUploadFileState> = {};
|
|
67
57
|
if (this.props.maxCount !== prevProps.maxCount) next.maxCount = this.props.maxCount;
|
|
68
|
-
if (this.props.
|
|
69
|
-
if (this.props.visibility !== prevProps.visibility) next.visibility = this.props.visibility;
|
|
58
|
+
if (this.props.isPublic !== prevProps.isPublic) next.isPublic = this.props.isPublic;
|
|
70
59
|
|
|
71
60
|
const prevValue = prevProps.value ?? null;
|
|
72
61
|
const curValue = this.props.value ?? null;
|
|
@@ -142,12 +131,6 @@ export class FieldUploadFile extends React.Component<FieldUploadFileProps, Field
|
|
|
142
131
|
};
|
|
143
132
|
|
|
144
133
|
render() {
|
|
145
|
-
if (this.state.cropImage) {
|
|
146
|
-
return <ImgCrop cropperProps={this.props.cropperProps} modalTitle={'裁剪图片'} fillColor={null}>
|
|
147
|
-
{this.getUpload()}
|
|
148
|
-
</ImgCrop>;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
134
|
return <>
|
|
152
135
|
{this.getUpload()}
|
|
153
136
|
<Modal open={!!this.state.errorTitle} title={this.state.errorTitle} okText="确定"
|
|
@@ -167,7 +150,7 @@ export class FieldUploadFile extends React.Component<FieldUploadFileProps, Field
|
|
|
167
150
|
|
|
168
151
|
return <Upload
|
|
169
152
|
action={UrlUtils.contextPath('/admin/sysFile/upload')}
|
|
170
|
-
data={{
|
|
153
|
+
data={{isPublic: this.state.isPublic}}
|
|
171
154
|
listType={this.props.listType || 'picture-card'}
|
|
172
155
|
fileList={fileList}
|
|
173
156
|
onChange={this.handleChange}
|