@jiangood/open-admin 3.0.15 → 3.1.1
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 +15 -2
- package/src/framework/biz/OrgTree.tsx +10 -6
- package/src/framework/biz/PermActions.tsx +5 -3
- package/src/framework/biz/RoleTree.tsx +10 -6
- package/src/framework/biz/index.tsx +1 -0
- package/src/framework/components/ContextMenu/index.tsx +17 -1
- package/src/framework/components/DownloadModal/index.tsx +40 -33
- package/src/framework/components/DrawerForm/index.tsx +108 -0
- package/src/framework/components/FormModal/index.tsx +16 -9
- package/src/framework/components/NamedIcon/index.tsx +2 -2
- package/src/framework/components/OrgSwitcher/index.tsx +6 -7
- package/src/framework/components/PageLoading/index.tsx +3 -3
- package/src/framework/components/ProTable/index.tsx +28 -25
- package/src/framework/components/ValueType/index.tsx +1 -1
- package/src/framework/components/index.ts +1 -0
- package/src/framework/config/themeConfig.ts +5 -5
- package/src/framework/fields/BaseRemoteSelect/index.tsx +23 -21
- package/src/framework/fields/FieldBoolean/index.tsx +6 -6
- package/src/framework/fields/FieldDate/index.tsx +10 -10
- package/src/framework/fields/FieldDateRange/index.tsx +20 -20
- package/src/framework/fields/FieldDictSelect/index.tsx +2 -2
- package/src/framework/fields/FieldEditor/index.tsx +1 -1
- package/src/framework/fields/FieldNumberRange/index.tsx +16 -17
- package/src/framework/fields/FieldPercent/index.tsx +2 -2
- package/src/framework/fields/FieldRemoteSelect/index.tsx +4 -4
- package/src/framework/fields/FieldRemoteTree/index.tsx +1 -1
- package/src/framework/fields/FieldRemoteTreeCascader/index.tsx +1 -1
- package/src/framework/fields/FieldRemoteTreeSelect/index.tsx +1 -1
- package/src/framework/fields/FieldSysOrgTree/index.tsx +1 -1
- package/src/framework/fields/FieldSysOrgTreeSelect/index.tsx +1 -1
- package/src/framework/fields/FieldTable/index.tsx +15 -13
- package/src/framework/fields/FieldTableSelect/index.tsx +5 -5
- package/src/framework/fields/FieldUploadFile/index.tsx +3 -3
- package/src/framework/fields/FieldUploadImage/index.tsx +31 -29
- package/src/framework/fields/types.ts +0 -2
- package/src/framework/router/PageFrame.tsx +1 -1
- package/src/framework/router/matcher.ts +2 -2
- package/src/framework/utils/ArrayUtils.ts +2 -2
- package/src/framework/utils/DateUtils.ts +1 -1
- package/src/framework/utils/{system/DictUtils.ts → DictUtils.ts} +1 -1
- package/src/framework/utils/EventBus.ts +7 -7
- package/src/framework/utils/HttpClient.ts +283 -0
- package/src/framework/utils/{system/PageUtils.ts → PageUtils.ts} +4 -4
- package/src/framework/utils/{system/PermUtils.ts → PermUtils.ts} +3 -3
- package/src/framework/utils/StringUtils.ts +10 -8
- package/src/framework/utils/TreeUtils.ts +3 -3
- package/src/framework/utils/UrlUtils.ts +2 -2
- package/src/framework/utils/index.ts +4 -1
- package/src/framework/views/ViewApproveStatus/index.tsx +1 -2
- package/src/framework/views/ViewBoolean/index.tsx +4 -1
- package/src/framework/views/ViewFile/index.tsx +4 -4
- package/src/framework/views/ViewImage/index.tsx +2 -2
- package/src/framework/views/ViewPassword/index.tsx +3 -2
- package/src/framework/views/ViewText/index.tsx +12 -3
- package/src/framework/views/types.ts +2 -4
- package/src/layouts/admin/AdminTabs.jsx +9 -0
- package/src/layouts/admin/AdminTabs.less +2 -2
- package/src/layouts/admin/HeaderRight.jsx +8 -7
- package/src/layouts/admin/TabLayout.jsx +2 -2
- package/src/layouts/admin/index.jsx +15 -11
- package/src/layouts/admin/index.less +16 -1
- package/src/layouts/index.tsx +24 -18
- package/src/pages/404.jsx +1 -1
- package/src/pages/article/$code.jsx +4 -4
- package/src/pages/index.jsx +1 -1
- package/src/pages/public/login.jsx +34 -27
- package/src/pages/public/test.jsx +1 -1
- package/src/pages/standalone/forceUpdatePwd.jsx +9 -7
- package/src/pages/system/article/index.jsx +9 -8
- package/src/pages/system/dict/index.jsx +19 -16
- package/src/pages/system/file/index.jsx +9 -9
- package/src/pages/system/job/index.jsx +17 -17
- package/src/pages/system/log/index.jsx +5 -7
- package/src/pages/system/org/index.jsx +31 -18
- package/src/pages/system/role/index.jsx +13 -12
- package/src/pages/system/role/rolePerm.jsx +25 -21
- package/src/pages/system/user/index.jsx +35 -33
- package/src/pages/system/user/userPerm.jsx +12 -12
- package/src/pages/userCenter/index.jsx +11 -9
- package/src/pages/userCenter/permView.jsx +7 -7
- package/src/framework/utils/system/HttpUtils.ts +0 -97
- package/src/framework/utils/system/index.ts +0 -4
|
@@ -4,16 +4,16 @@ import {BaseRemoteSelect} from '../BaseRemoteSelect';
|
|
|
4
4
|
import type {SelectProps} from "antd/es/select";
|
|
5
5
|
import type {FieldProps} from '../types';
|
|
6
6
|
|
|
7
|
-
interface FieldRemoteSelectProps extends Omit<SelectProps, 'value' | 'onChange' | 'mode'>, FieldProps<
|
|
7
|
+
interface FieldRemoteSelectProps extends Omit<SelectProps, 'value' | 'onChange' | 'mode'>, FieldProps<unknown> {
|
|
8
8
|
url: string;
|
|
9
9
|
debounceTime?: number;
|
|
10
10
|
multiple?: boolean;
|
|
11
|
-
paramsProcessor?: (params:
|
|
12
|
-
responseProcessor?: (response:
|
|
11
|
+
paramsProcessor?: (params: Record<string, unknown>) => Record<string, unknown>;
|
|
12
|
+
responseProcessor?: (response: unknown) => unknown;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export class FieldRemoteSelect extends BaseRemoteSelect<FieldRemoteSelectProps> {
|
|
16
|
-
static defaultProps = {
|
|
16
|
+
static readonly defaultProps = {
|
|
17
17
|
placeholder: '请搜索选择',
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -20,7 +20,7 @@ export class FieldRemoteTree extends BaseRemoteSelect {
|
|
|
20
20
|
<Tree
|
|
21
21
|
multiple
|
|
22
22
|
checkable
|
|
23
|
-
onCheck={(checkedInfo) => this.props.onChange
|
|
23
|
+
onCheck={(checkedInfo) => this.props.onChange?.(checkedInfo.checked)}
|
|
24
24
|
checkedKeys={this.props.value}
|
|
25
25
|
treeData={this.state.data}
|
|
26
26
|
defaultExpandAll
|
|
@@ -28,7 +28,7 @@ export class FieldRemoteTreeCascader extends BaseRemoteSelect {
|
|
|
28
28
|
<Cascader
|
|
29
29
|
options={data}
|
|
30
30
|
onChange={(arr) => {
|
|
31
|
-
onChange
|
|
31
|
+
onChange?.(arr[arr.length - 1]);
|
|
32
32
|
}}
|
|
33
33
|
value={arr}
|
|
34
34
|
fieldNames={{ label: 'title', value: 'key' }}
|
|
@@ -16,12 +16,12 @@ export interface FieldTableColumn {
|
|
|
16
16
|
/** 列宽 */
|
|
17
17
|
width?: number | string;
|
|
18
18
|
/** 自定义渲染(返回的组件会被注入 value/onChange) */
|
|
19
|
-
render?: (value:
|
|
19
|
+
render?: (value: unknown, record: Record<string, unknown>, index: number) => React.ReactElement;
|
|
20
20
|
/** 其余 antd Table 列属性 */
|
|
21
|
-
[key: string]:
|
|
21
|
+
[key: string]: unknown;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export interface FieldTableProps extends FieldProps<Record<string,
|
|
24
|
+
export interface FieldTableProps extends FieldProps<Record<string, unknown>[]> {
|
|
25
25
|
/** 列配置(操作列由组件自动追加) */
|
|
26
26
|
columns: FieldTableColumn[];
|
|
27
27
|
/** 容器样式 */
|
|
@@ -29,7 +29,7 @@ export interface FieldTableProps extends FieldProps<Record<string, any>[]> {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
interface FieldTableState {
|
|
32
|
-
dataSource: Record<string,
|
|
32
|
+
dataSource: Record<string, unknown>[];
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -84,13 +84,13 @@ export class FieldTable extends React.Component<FieldTableProps, FieldTableState
|
|
|
84
84
|
dataSource: []
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
onCellChange = (index: number, dataIndex: string | undefined, e:
|
|
87
|
+
onCellChange = (index: number, dataIndex: string | undefined, e: unknown) => {
|
|
88
88
|
const {dataSource} = this.state;
|
|
89
89
|
const row = dataSource[index];
|
|
90
90
|
|
|
91
|
-
let v = e;
|
|
91
|
+
let v: unknown = e;
|
|
92
92
|
if (e != null && typeof e === 'object' && 'target' in e) {
|
|
93
|
-
v = e.target.value;
|
|
93
|
+
v = (e as {target: {value: unknown}}).target.value;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
const next = [...dataSource];
|
|
@@ -104,25 +104,27 @@ export class FieldTable extends React.Component<FieldTableProps, FieldTableState
|
|
|
104
104
|
this.setState({dataSource}, this.notifyParent);
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
remove = (record: Record<string,
|
|
107
|
+
remove = (record: Record<string, unknown>) => {
|
|
108
108
|
const {dataSource} = this.state;
|
|
109
109
|
this.setState({dataSource: dataSource.filter(item => item !== record)}, this.notifyParent);
|
|
110
110
|
};
|
|
111
111
|
|
|
112
112
|
notifyParent = () => {
|
|
113
113
|
const {dataSource} = this.state;
|
|
114
|
-
this.props.onChange
|
|
114
|
+
this.props.onChange?.(dataSource);
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
+
renderFooter = () => <Button type='dashed'
|
|
118
|
+
icon={<PlusOutlined/>}
|
|
119
|
+
onClick={this.add}>增加一行
|
|
120
|
+
</Button>;
|
|
121
|
+
|
|
117
122
|
render() {
|
|
118
123
|
return <div className='edit-table' style={this.props.style}>
|
|
119
124
|
<Table columns={this.columns}
|
|
120
125
|
dataSource={this.state.dataSource}
|
|
121
126
|
size='small'
|
|
122
|
-
footer={
|
|
123
|
-
icon={<PlusOutlined/>}
|
|
124
|
-
onClick={this.add}>增加一行
|
|
125
|
-
</Button>}
|
|
127
|
+
footer={this.renderFooter}
|
|
126
128
|
pagination={false}
|
|
127
129
|
>
|
|
128
130
|
|
|
@@ -2,14 +2,14 @@ import React from "react";
|
|
|
2
2
|
import {Button, Select} from "antd";
|
|
3
3
|
import type {TableColumnsType} from "antd";
|
|
4
4
|
import {ProTable} from "../../components";
|
|
5
|
-
import {
|
|
5
|
+
import {HttpClient} from "../../utils";
|
|
6
6
|
import type {FieldProps} from '../types';
|
|
7
7
|
|
|
8
8
|
export interface FieldTableSelectProps extends FieldProps<string> {
|
|
9
9
|
/** 数据加载地址 */
|
|
10
10
|
url: string;
|
|
11
11
|
/** 表格列配置(操作列由组件自动追加) */
|
|
12
|
-
columns: TableColumnsType<Record<string,
|
|
12
|
+
columns: TableColumnsType<Record<string, unknown>>;
|
|
13
13
|
/** 占位文本,默认 请搜索选择 */
|
|
14
14
|
placeholder?: string;
|
|
15
15
|
}
|
|
@@ -26,7 +26,7 @@ interface FieldTableSelectState {
|
|
|
26
26
|
*/
|
|
27
27
|
export class FieldTableSelect extends React.Component<FieldTableSelectProps, FieldTableSelectState> {
|
|
28
28
|
|
|
29
|
-
static defaultProps = {
|
|
29
|
+
static readonly defaultProps = {
|
|
30
30
|
placeholder: '请搜索选择',
|
|
31
31
|
};
|
|
32
32
|
|
|
@@ -62,13 +62,13 @@ export class FieldTableSelect extends React.Component<FieldTableSelectProps, Fie
|
|
|
62
62
|
label: record.name,
|
|
63
63
|
open: false
|
|
64
64
|
});
|
|
65
|
-
this.props.onChange
|
|
65
|
+
this.props.onChange?.(record.id);
|
|
66
66
|
}}>选择</Button>;
|
|
67
67
|
}
|
|
68
68
|
}]}
|
|
69
69
|
request={(params) => {
|
|
70
70
|
params.selected = this.props.value;
|
|
71
|
-
return
|
|
71
|
+
return HttpClient.get(this.props.url, params);
|
|
72
72
|
}}>
|
|
73
73
|
</ProTable>;
|
|
74
74
|
};
|
|
@@ -88,7 +88,7 @@ export class FieldUploadFile extends React.Component<FieldUploadFileProps, Field
|
|
|
88
88
|
if (f.response) { // 新上传的
|
|
89
89
|
const ajaxResult = f.response;
|
|
90
90
|
if (ajaxResult.success) {
|
|
91
|
-
const {objectName
|
|
91
|
+
const {objectName} = ajaxResult.data;
|
|
92
92
|
f.objectName = objectName;
|
|
93
93
|
objectNames.push(objectName);
|
|
94
94
|
} else {
|
|
@@ -102,9 +102,9 @@ export class FieldUploadFile extends React.Component<FieldUploadFileProps, Field
|
|
|
102
102
|
return objectNames;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
handleChange = ({fileList,
|
|
105
|
+
handleChange = ({fileList, file}: UploadChangeParam<SysUploadFile>) => {
|
|
106
106
|
const rs = file.response;
|
|
107
|
-
if (rs
|
|
107
|
+
if (rs?.success === false) {
|
|
108
108
|
this.setState({errorTitle: '上传失败', errorContent: rs.message});
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
@@ -4,9 +4,7 @@ import {DeleteOutlined, EyeOutlined, PlusOutlined} from "@ant-design/icons";
|
|
|
4
4
|
import Compressor from "compressorjs";
|
|
5
5
|
import Cropper from "cropperjs";
|
|
6
6
|
import "cropperjs/dist/cropper.css";
|
|
7
|
-
import {
|
|
8
|
-
import {ObjectUtils} from "../../utils";
|
|
9
|
-
import {UrlUtils} from "../../utils";
|
|
7
|
+
import {HttpClient, ObjectUtils, UrlUtils} from "../../utils";
|
|
10
8
|
import type {FieldProps} from '../types';
|
|
11
9
|
|
|
12
10
|
export interface FieldUploadImageProps extends FieldProps<string> {
|
|
@@ -93,7 +91,7 @@ function readDims(url: string): Promise<Dims> {
|
|
|
93
91
|
|
|
94
92
|
function compressToFile(source: Blob, options: {maxWidth?: number; maxHeight?: number; width?: number; height?: number; quality?: number}): Promise<File> {
|
|
95
93
|
return new Promise((resolve, reject) => {
|
|
96
|
-
new Compressor(source, {
|
|
94
|
+
new Compressor(source, { // NOSONAR (typescript:S1848) — compressorjs 通过构造函数副作用异步压缩,回调内 resolve/reject,实例无需保留
|
|
97
95
|
maxWidth: options.maxWidth,
|
|
98
96
|
maxHeight: options.maxHeight,
|
|
99
97
|
width: options.width,
|
|
@@ -141,9 +139,9 @@ async function compressToTarget(source: Blob, maxWidth: number | undefined, targ
|
|
|
141
139
|
return best;
|
|
142
140
|
}
|
|
143
141
|
|
|
144
|
-
export class FieldUploadImage extends React.Component<FieldUploadImageProps, FieldUploadImageState> {
|
|
142
|
+
export class FieldUploadImage extends React.Component<FieldUploadImageProps, FieldUploadImageState> { // NOSONAR: state 构造器中按 props 初始化,无法全部 readonly
|
|
145
143
|
|
|
146
|
-
state: FieldUploadImageState = {
|
|
144
|
+
state: FieldUploadImageState = { // NOSONAR: 构造器中按 props 初始化,无法 readonly
|
|
147
145
|
// 传入的参数
|
|
148
146
|
maxCount: 1,
|
|
149
147
|
thumbWidth: 300,
|
|
@@ -169,10 +167,10 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
169
167
|
constructor(props: FieldUploadImageProps) {
|
|
170
168
|
super(props);
|
|
171
169
|
ObjectUtils.copyPropertyIfPresent(props, this.state);
|
|
172
|
-
if (
|
|
170
|
+
if (props.value) this.state.objectNames = props.value.split(',');
|
|
173
171
|
}
|
|
174
172
|
|
|
175
|
-
componentDidUpdate(prevProps: FieldUploadImageProps, prevState: FieldUploadImageState) {
|
|
173
|
+
componentDidUpdate(prevProps: FieldUploadImageProps, prevState: FieldUploadImageState) { // NOSONAR: 顺序同步多个 props 到 state,拆分反而更难读
|
|
176
174
|
const next: Partial<FieldUploadImageState> = {};
|
|
177
175
|
if (this.props.maxCount !== prevProps.maxCount) next.maxCount = this.props.maxCount;
|
|
178
176
|
if (this.props.thumbWidth !== prevProps.thumbWidth) next.thumbWidth = this.props.thumbWidth;
|
|
@@ -199,7 +197,7 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
199
197
|
if (prevState.cropRatio !== this.state.cropRatio && this.cropperRef) {
|
|
200
198
|
if (!this.state.cropRatio) {
|
|
201
199
|
const box = this.cropperRef.getCropBoxData();
|
|
202
|
-
this.cropperRef.setAspectRatio(NaN);
|
|
200
|
+
this.cropperRef.setAspectRatio(Number.NaN);
|
|
203
201
|
this.cropperRef.setCropBoxData(box);
|
|
204
202
|
} else {
|
|
205
203
|
this.cropperRef.setAspectRatio(this.state.cropRatio.width / this.state.cropRatio.height);
|
|
@@ -229,7 +227,7 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
229
227
|
const init = () => {
|
|
230
228
|
if (this.cropperRef) this.cropperRef.destroy();
|
|
231
229
|
this.cropperRef = new Cropper(el, {
|
|
232
|
-
aspectRatio: this.state.cropRatio ? this.state.cropRatio.width / this.state.cropRatio.height : NaN,
|
|
230
|
+
aspectRatio: this.state.cropRatio ? this.state.cropRatio.width / this.state.cropRatio.height : Number.NaN,
|
|
233
231
|
viewMode: 1,
|
|
234
232
|
autoCropArea: 0.85,
|
|
235
233
|
dragMode: 'move',
|
|
@@ -293,7 +291,7 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
293
291
|
this.previewUrlsRef = [cUrl];
|
|
294
292
|
this.setState({preview: {cUrl, cFile, cSize: cFile.size, cdims}, tool: undefined});
|
|
295
293
|
message.success(`已压缩:${cdims.width} x ${cdims.height} / ${formatSize(cFile.size)}`);
|
|
296
|
-
} catch
|
|
294
|
+
} catch {
|
|
297
295
|
message.error('压缩失败');
|
|
298
296
|
}
|
|
299
297
|
};
|
|
@@ -320,7 +318,7 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
320
318
|
this.setState({originalDims: dims});
|
|
321
319
|
// 默认展示原图,不做压缩处理,用户可点击「压缩」按钮手动压缩
|
|
322
320
|
await this.loadOriginalPreview(file, url, dims);
|
|
323
|
-
} catch
|
|
321
|
+
} catch {
|
|
324
322
|
message.error('读取图片失败');
|
|
325
323
|
this.closeModal();
|
|
326
324
|
return;
|
|
@@ -365,22 +363,34 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
365
363
|
fd.append('file', this.state.preview.cFile);
|
|
366
364
|
fd.append('thumb', tFile);
|
|
367
365
|
fd.append('isPublic', String(this.state.isPublic));
|
|
368
|
-
const rs = await
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
366
|
+
const rs = await HttpClient.post('admin/sysFile/uploadImage', fd, null, {toastError: false});
|
|
367
|
+
this.setState(
|
|
368
|
+
(prevState) => ({objectNames: [...prevState.objectNames, rs.data.objectName]}),
|
|
369
|
+
() => this.props.onChange?.(this.state.objectNames.join(','))
|
|
370
|
+
);
|
|
372
371
|
this.closeModal();
|
|
373
372
|
} catch (e) {
|
|
374
|
-
message.error(
|
|
373
|
+
message.error(HttpClient.errToMsg(e));
|
|
375
374
|
} finally {
|
|
376
375
|
this.setState({uploading: false});
|
|
377
376
|
}
|
|
378
377
|
};
|
|
379
378
|
|
|
380
379
|
private removeImage = (name: string) => {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
380
|
+
this.setState(
|
|
381
|
+
(prevState) => ({objectNames: prevState.objectNames.filter((n) => n !== name)}),
|
|
382
|
+
() => this.props.onChange?.(this.state.objectNames.join(','))
|
|
383
|
+
);
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
private renderCanvas = (preview, canvasImg, originalUrl) => {
|
|
387
|
+
if (this.state.tool === 'crop') {
|
|
388
|
+
return <img key="crop-canvas" ref={this.imgRef} src={preview?.cUrl || originalUrl} style={{maxWidth: '100%', maxHeight: '100%'}} alt="待裁切"/>;
|
|
389
|
+
}
|
|
390
|
+
if (canvasImg?.url) {
|
|
391
|
+
return <img src={canvasImg.url} style={{maxWidth: '100%', maxHeight: '100%'}} alt="预览"/>;
|
|
392
|
+
}
|
|
393
|
+
return <div style={{color: '#999'}}>生成中...</div>;
|
|
384
394
|
};
|
|
385
395
|
|
|
386
396
|
render() {
|
|
@@ -479,13 +489,7 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
479
489
|
flex: 1, minHeight: 0, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
480
490
|
background: '#f5f5f5', borderRadius: 8, border: '1px dashed #d9d9d9', position: 'relative', overflow: 'hidden',
|
|
481
491
|
}}>
|
|
482
|
-
{
|
|
483
|
-
<img key="crop-canvas" ref={this.imgRef} src={preview?.cUrl || originalUrl} style={{maxWidth: '100%', maxHeight: '100%'}} alt="待裁切"/>
|
|
484
|
-
) : canvasImg?.url ? (
|
|
485
|
-
<img src={canvasImg.url} style={{maxWidth: '100%', maxHeight: '100%'}} alt="预览"/>
|
|
486
|
-
) : (
|
|
487
|
-
<div style={{color: '#999'}}>生成中...</div>
|
|
488
|
-
)}
|
|
492
|
+
{this.renderCanvas(preview, canvasImg, originalUrl)}
|
|
489
493
|
</div>
|
|
490
494
|
</div>
|
|
491
495
|
|
|
@@ -506,7 +510,6 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
506
510
|
{tool !== 'crop' && <Divider style={{margin: '0 0 12px'}}/>}
|
|
507
511
|
<div style={{fontWeight: 600, marginBottom: 8}}>{tool === 'crop' ? '裁切信息' : '图片信息'}</div>
|
|
508
512
|
{tool === 'crop' ? (
|
|
509
|
-
<>
|
|
510
513
|
<Radio.Group
|
|
511
514
|
value={cropRatio ? formatRatio(cropRatio.width, cropRatio.height) : 'free'}
|
|
512
515
|
onChange={(e) => {
|
|
@@ -521,7 +524,6 @@ export class FieldUploadImage extends React.Component<FieldUploadImageProps, Fie
|
|
|
521
524
|
</Radio>
|
|
522
525
|
))}
|
|
523
526
|
</Radio.Group>
|
|
524
|
-
</>
|
|
525
527
|
) : (
|
|
526
528
|
<>
|
|
527
529
|
{canvasImg && (
|
|
@@ -10,7 +10,7 @@ interface PageFrameProps {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export class PageFrame extends React.Component<PageFrameProps> {
|
|
13
|
-
componentRef = React.createRef<
|
|
13
|
+
componentRef = React.createRef<{onShow?: () => void}>();
|
|
14
14
|
|
|
15
15
|
componentDidMount() {
|
|
16
16
|
this.callOnShowIfActive();
|
|
@@ -6,7 +6,7 @@ function safeDecodeURIComponent(s: string): string {
|
|
|
6
6
|
|
|
7
7
|
export interface RouteDef {
|
|
8
8
|
path: string;
|
|
9
|
-
component: ComponentType<
|
|
9
|
+
component: ComponentType<unknown>;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
interface InternalRoute extends RouteDef {
|
|
@@ -14,7 +14,7 @@ interface InternalRoute extends RouteDef {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export interface MatchResult {
|
|
17
|
-
component: ComponentType<
|
|
17
|
+
component: ComponentType<unknown>;
|
|
18
18
|
params: Record<string, string>;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export class ArrayUtils {
|
|
2
2
|
static contains<T>(arr: T[], item: T): boolean {
|
|
3
|
-
return arr.
|
|
3
|
+
return arr.includes(item);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
static containsAny<T>(arr: T[], ...items: T[]): boolean {
|
|
@@ -10,7 +10,7 @@ export class ArrayUtils {
|
|
|
10
10
|
return false;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
static maxBy<T extends Record<K,
|
|
13
|
+
static maxBy<T extends Record<K, unknown>, K extends keyof T>(arr: T[], key: K): T | undefined {
|
|
14
14
|
if (arr == null || arr.length === 0) return undefined;
|
|
15
15
|
let maxElement: T | undefined = undefined;
|
|
16
16
|
let maxValue = -Infinity;
|
|
@@ -62,7 +62,7 @@ export class DateUtils {
|
|
|
62
62
|
static friendlyTotalTime(time: number | string | null): string | null {
|
|
63
63
|
if (time == null || time === '-') return null;
|
|
64
64
|
let seconds: number;
|
|
65
|
-
if (typeof time === 'string') seconds = parseInt(time, 10) / 1000;
|
|
65
|
+
if (typeof time === 'string') seconds = Number.parseInt(time, 10) / 1000;
|
|
66
66
|
else seconds = time / 1000;
|
|
67
67
|
seconds = Math.floor(seconds);
|
|
68
68
|
if (seconds < 60) return seconds + '秒';
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
type EventCallback = (...args:
|
|
1
|
+
type EventCallback = (...args: unknown[]) => void;
|
|
2
2
|
|
|
3
3
|
interface EventEntry {
|
|
4
4
|
fn: EventCallback & { __callback?: EventCallback };
|
|
5
|
-
ctx?:
|
|
5
|
+
ctx?: unknown;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class EventBus {
|
|
9
9
|
private static __stack: Record<string, EventEntry[]> = {};
|
|
10
10
|
|
|
11
|
-
static on<T extends
|
|
11
|
+
static on<T extends unknown[] = []>(name: string, callback: (...args: T) => void, ctx?: unknown): () => void {
|
|
12
12
|
if (!EventBus.__stack[name]) {
|
|
13
13
|
EventBus.__stack[name] = [];
|
|
14
14
|
}
|
|
@@ -16,9 +16,9 @@ export class EventBus {
|
|
|
16
16
|
return () => EventBus.off(name, callback);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
static once<T extends
|
|
19
|
+
static once<T extends unknown[] = []>(name: string, callback: (...args: T) => void, ctx?: unknown): () => void {
|
|
20
20
|
const unsubscribe = () => EventBus.off(name, callback);
|
|
21
|
-
const listener: EventEntry['fn'] = (...args:
|
|
21
|
+
const listener: EventEntry['fn'] = (...args: unknown[]) => {
|
|
22
22
|
EventBus.off(name, listener);
|
|
23
23
|
callback.apply(ctx, args);
|
|
24
24
|
};
|
|
@@ -28,7 +28,7 @@ export class EventBus {
|
|
|
28
28
|
return unsubscribe;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
static emit<T extends
|
|
31
|
+
static emit<T extends unknown[] = []>(name: string, ...args: T): void {
|
|
32
32
|
const list = EventBus.__stack[name];
|
|
33
33
|
if (list !== undefined) {
|
|
34
34
|
list.slice(0).forEach(entry => {
|
|
@@ -37,7 +37,7 @@ export class EventBus {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
static off<T extends
|
|
40
|
+
static off<T extends unknown[] = []>(name: string, callback?: (...args: T) => void): void {
|
|
41
41
|
const list = EventBus.__stack[name];
|
|
42
42
|
if (list === undefined) return;
|
|
43
43
|
if (callback === undefined) {
|