@ecoding/components.antd 0.2.34 → 0.2.35
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/lib/core/confirm/index.d.ts +1 -1
- package/lib/core/drawer/index.d.ts +1 -1
- package/lib/core/form.label/index.d.ts +13 -4
- package/lib/core/form.label/index.js +52 -6
- package/lib/core/form.label.attachment/index.d.ts +14 -0
- package/lib/core/form.label.attachment/index.js +87 -0
- package/lib/core/form.list/index.d.ts +1 -0
- package/lib/core/form.list/index.js +6 -6
- package/lib/core/modal/index.d.ts +1 -1
- package/lib/core/multiple-upload/index.d.ts +1 -0
- package/lib/core/multiple-upload/index.js +1 -1
- package/lib/core/single-img-upload/index.js +4 -4
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +3 -3
|
@@ -5,7 +5,7 @@ interface IComfirm {
|
|
|
5
5
|
okText?: string;
|
|
6
6
|
width?: number;
|
|
7
7
|
cancelText?: string;
|
|
8
|
-
okType?: "primary" | "default" | "
|
|
8
|
+
okType?: "primary" | "default" | "dashed" | "link" | "text" | "danger" | undefined;
|
|
9
9
|
onOk: () => Promise<any>;
|
|
10
10
|
onCancel?: () => Promise<any>;
|
|
11
11
|
}
|
|
@@ -14,7 +14,7 @@ export interface IDrawerProps {
|
|
|
14
14
|
placement?: DrawerProps["placement"];
|
|
15
15
|
okDanger?: boolean;
|
|
16
16
|
title?: React.ReactNode;
|
|
17
|
-
okType?: "text" | "link" | "
|
|
17
|
+
okType?: "text" | "link" | "default" | "primary" | "dashed" | undefined;
|
|
18
18
|
okText?: string;
|
|
19
19
|
cancelText?: string;
|
|
20
20
|
mask?: boolean;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
2
|
interface IProps {
|
|
3
|
-
value?: string;
|
|
4
|
-
type?:
|
|
3
|
+
value?: string | string[];
|
|
4
|
+
type?: 'secondary' | 'success' | 'warning' | 'danger';
|
|
5
|
+
splitDot?: string;
|
|
5
6
|
empty?: React.ReactNode;
|
|
6
7
|
disabled?: boolean;
|
|
7
8
|
mark?: boolean;
|
|
@@ -13,7 +14,15 @@ interface IProps {
|
|
|
13
14
|
italic?: boolean;
|
|
14
15
|
link?: {
|
|
15
16
|
href?: string;
|
|
16
|
-
target?:
|
|
17
|
+
target?: '_blank' | '_self';
|
|
18
|
+
download?: string;
|
|
19
|
+
};
|
|
20
|
+
tag?: boolean | {
|
|
21
|
+
bordered?: boolean;
|
|
22
|
+
color?: "success" | "processing" | "error" | "warning" | "magenta" | "red" | "volcano" | "orange" | "gold" | "lime" | "green" | "cyan" | "blue" | "geekblue" | "purple";
|
|
23
|
+
};
|
|
24
|
+
badge?: boolean | {
|
|
25
|
+
status?: "success" | "error" | "processing" | "warning";
|
|
17
26
|
};
|
|
18
27
|
}
|
|
19
28
|
declare const C: React.FC<IProps>;
|
|
@@ -1,9 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import { isSomething } from '@ecoding/helper.is';
|
|
14
|
+
import { Typography, Space, Tag, Badge } from 'antd';
|
|
15
|
+
const C = (_a) => {
|
|
16
|
+
var { badge, tag } = _a, props = __rest(_a, ["badge", "tag"]);
|
|
17
|
+
if (!isSomething(props.value) || Array.isArray(props.value) && props.value.length === 0) {
|
|
18
|
+
return React.createElement(Typography.Text, null, props.empty || "");
|
|
19
|
+
}
|
|
20
|
+
if (badge) {
|
|
21
|
+
const opts = badge === true ? {} : badge;
|
|
22
|
+
if (!Array.isArray(props.value)) {
|
|
23
|
+
return React.createElement(Badge, { status: opts.status || "default", text: props.value });
|
|
24
|
+
}
|
|
25
|
+
return (React.createElement(Space, { split: props.splitDot, wrap: true }, props.value.map((item) => {
|
|
26
|
+
return React.createElement(Badge, { status: opts.status || "default", text: props.value });
|
|
27
|
+
})));
|
|
28
|
+
}
|
|
29
|
+
if (tag) {
|
|
30
|
+
const opts = tag === true ? {} : tag;
|
|
31
|
+
if (!Array.isArray(props.value)) {
|
|
32
|
+
return React.createElement(Tag, { style: { marginInlineEnd: 0 }, color: opts.color, bordered: opts.bordered }, props.value);
|
|
33
|
+
}
|
|
34
|
+
return (React.createElement(Space, { split: props.splitDot, wrap: true }, props.value.map((item) => {
|
|
35
|
+
return React.createElement(Tag, { style: { marginInlineEnd: 0 }, color: opts.color, bordered: opts.bordered }, item);
|
|
36
|
+
})));
|
|
37
|
+
}
|
|
38
|
+
if (!Array.isArray(props.value)) {
|
|
39
|
+
if (props.link) {
|
|
40
|
+
return React.createElement(Typography.Link, Object.assign({}, props.link), props.value);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
return (React.createElement(Typography.Text, { type: props.type, italic: props.italic, strong: props.strong, delete: props.delete, underline: props.underline, disabled: props.disabled, mark: props.mark, code: props.code, keyboard: props.keyboard }, props.value));
|
|
44
|
+
}
|
|
6
45
|
}
|
|
7
|
-
return React.createElement(
|
|
46
|
+
return (React.createElement(Space, { split: props.splitDot, wrap: true }, props.value.map((item) => {
|
|
47
|
+
if (props.link) {
|
|
48
|
+
return React.createElement(Typography.Link, Object.assign({}, props.link), item);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
return (React.createElement(Typography.Text, { type: props.type, italic: props.italic, strong: props.strong, delete: props.delete, underline: props.underline, disabled: props.disabled, mark: props.mark, code: props.code, keyboard: props.keyboard }, item));
|
|
52
|
+
}
|
|
53
|
+
})));
|
|
8
54
|
};
|
|
9
55
|
export default C;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface IRes {
|
|
3
|
+
name: string;
|
|
4
|
+
url: string;
|
|
5
|
+
[props: string]: any;
|
|
6
|
+
}
|
|
7
|
+
interface IProps {
|
|
8
|
+
value?: IRes | IRes[];
|
|
9
|
+
empty?: React.ReactNode;
|
|
10
|
+
i18n?: any;
|
|
11
|
+
render?: (infos: IRes[]) => React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
declare const C: React.FC<IProps>;
|
|
14
|
+
export default C;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { isSomething } from '@ecoding/helper.is';
|
|
3
|
+
import { LinkOutlined, CloudDownloadOutlined, EyeOutlined } from '@ant-design/icons';
|
|
4
|
+
import { Typography, Popover, Tag, Checkbox, Space } from 'antd';
|
|
5
|
+
const InfosRender = ({ infos, i18n }) => {
|
|
6
|
+
const [checkedList, setCheckedList] = useState([]);
|
|
7
|
+
const style = {
|
|
8
|
+
display: 'flex',
|
|
9
|
+
justifyContent: 'space-between',
|
|
10
|
+
margin: 0
|
|
11
|
+
};
|
|
12
|
+
const checkAll = infos.length === checkedList.length;
|
|
13
|
+
const indeterminate = checkedList.length > 0 && checkedList.length < infos.length;
|
|
14
|
+
function downloadFile(url) {
|
|
15
|
+
//下载文件
|
|
16
|
+
let a = document.createElement("a");
|
|
17
|
+
a.setAttribute("href", url);
|
|
18
|
+
a.setAttribute("download", "");
|
|
19
|
+
a.setAttribute("target", "_blank");
|
|
20
|
+
const evt = new MouseEvent("click", {
|
|
21
|
+
bubbles: true,
|
|
22
|
+
cancelable: true,
|
|
23
|
+
view: window,
|
|
24
|
+
});
|
|
25
|
+
// let clickEvent = document.createEvent("MouseEvents");
|
|
26
|
+
// clickEvent.initEvent("click", true, true);
|
|
27
|
+
a.dispatchEvent(evt);
|
|
28
|
+
}
|
|
29
|
+
const checkChange = (keys) => {
|
|
30
|
+
setCheckedList(keys);
|
|
31
|
+
};
|
|
32
|
+
const onCheckAllChange = (e) => {
|
|
33
|
+
if (e.target.checked) {
|
|
34
|
+
setCheckedList(infos.map((info) => info.url));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
setCheckedList([]);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const downLoadAll = () => {
|
|
41
|
+
checkedList.forEach(key => {
|
|
42
|
+
downloadFile(key);
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
return (React.createElement("ul", { style: { width: 300, overflow: "hidden" } },
|
|
46
|
+
React.createElement(Checkbox.Group, { style: { display: "block" }, onChange: checkChange, value: checkedList }, infos.map((info, i) => {
|
|
47
|
+
return (React.createElement("li", { style: { marginBottom: 6 } },
|
|
48
|
+
React.createElement("div", { style: style },
|
|
49
|
+
infos.length > 1 ? (React.createElement(Checkbox, { value: info.url },
|
|
50
|
+
React.createElement(Typography.Text, { style: { width: 250 }, ellipsis: true, title: info.name },
|
|
51
|
+
React.createElement(LinkOutlined, null),
|
|
52
|
+
" ",
|
|
53
|
+
info.name))) : (React.createElement(Typography.Text, { style: { width: 250 }, ellipsis: true, title: info.name },
|
|
54
|
+
React.createElement(LinkOutlined, null),
|
|
55
|
+
" ",
|
|
56
|
+
info.name)),
|
|
57
|
+
React.createElement(Typography.Link, { download: info.name, title: info.name, href: info.url, target: "_blank" },
|
|
58
|
+
React.createElement(CloudDownloadOutlined, null))),
|
|
59
|
+
info.time || info.user ? (React.createElement("div", { style: style },
|
|
60
|
+
React.createElement(Typography.Text, { type: "secondary", style: { fontSize: 12 } }, info.time),
|
|
61
|
+
React.createElement(Typography.Text, { type: "secondary", style: { fontSize: 12 } }, info.user))) : null));
|
|
62
|
+
})),
|
|
63
|
+
infos.length > 1 ? (React.createElement("li", { style: { marginTop: 10, paddingTop: 10, borderTop: "1px dashed #eee" } },
|
|
64
|
+
React.createElement(Space, null,
|
|
65
|
+
React.createElement(Checkbox, { indeterminate: indeterminate, onChange: onCheckAllChange, checked: checkAll }, i18n ? i18n.$t('global.checkbox.all', '全选') : '全选'),
|
|
66
|
+
React.createElement(Typography.Link, { disabled: checkedList.length === 0, onClick: () => downLoadAll() }, i18n ? i18n.$t('global.batch.download', '批量下载') : '批量下载')))) : null));
|
|
67
|
+
};
|
|
68
|
+
const C = ({ value, empty, render, i18n }) => {
|
|
69
|
+
if (!isSomething(value) || (Array.isArray(value) && value.length === 0)) {
|
|
70
|
+
return React.createElement(React.Fragment, null, empty || '-');
|
|
71
|
+
}
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
return (React.createElement(Popover, { destroyTooltipOnHide: true, placement: "right", trigger: "hover", title: "Uploaded", content: render ? render(value) : React.createElement(InfosRender, { i18n: i18n, infos: value }) },
|
|
74
|
+
React.createElement(Tag, { icon: React.createElement(EyeOutlined, null), color: "processing" }, i18n ? i18n.$t('global.attachment', '附件') : '附件')));
|
|
75
|
+
}
|
|
76
|
+
if (typeof value === 'string') {
|
|
77
|
+
return (React.createElement(Typography.Link, { download: "", title: value, href: value, target: "_blank" },
|
|
78
|
+
React.createElement(LinkOutlined, null),
|
|
79
|
+
" ",
|
|
80
|
+
i18n ? i18n.$t('global.attachment', '附件') : '附件'));
|
|
81
|
+
}
|
|
82
|
+
return (React.createElement(Typography.Link, { download: value === null || value === void 0 ? void 0 : value.name, title: value === null || value === void 0 ? void 0 : value.name, href: value === null || value === void 0 ? void 0 : value.url, target: "_blank" },
|
|
83
|
+
React.createElement(LinkOutlined, null),
|
|
84
|
+
" ",
|
|
85
|
+
i18n ? i18n.$t('global.attachment', '附件') : '附件'));
|
|
86
|
+
};
|
|
87
|
+
export default C;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { Typography, Form, Button } from 'antd';
|
|
3
3
|
import { PlusCircleOutlined } from '@ant-design/icons';
|
|
4
|
-
const C = ({ columns, rules, name, hideOperation, operation, i18n }) => {
|
|
4
|
+
const C = ({ columns, rules, name, hideOperation, hideBottom, operation, i18n }) => {
|
|
5
5
|
const tdStyle = {
|
|
6
6
|
verticalAlign: 'top',
|
|
7
7
|
lineHeight: '32px',
|
|
@@ -33,7 +33,7 @@ const C = ({ columns, rules, name, hideOperation, operation, i18n }) => {
|
|
|
33
33
|
React.createElement("table", { style: { width: widths } },
|
|
34
34
|
React.createElement("thead", null,
|
|
35
35
|
React.createElement("tr", null,
|
|
36
|
-
React.createElement("th", { style: Object.assign({}, thStyle, { width: '60px' }) }, i18n ? i18n.$t("global.num") : "序号"),
|
|
36
|
+
React.createElement("th", { style: Object.assign({}, thStyle, { width: '60px' }) }, i18n ? i18n.$t("global.num", "序号") : "序号"),
|
|
37
37
|
columns.map((column, i) => {
|
|
38
38
|
if (column.require) {
|
|
39
39
|
return (React.createElement("th", { style: Object.assign({}, thStyle, { width: column.width || 200 }) },
|
|
@@ -43,7 +43,7 @@ const C = ({ columns, rules, name, hideOperation, operation, i18n }) => {
|
|
|
43
43
|
}
|
|
44
44
|
return React.createElement("th", { style: Object.assign({}, thStyle, { width: column.width || 200 }) }, column.title);
|
|
45
45
|
}),
|
|
46
|
-
hideOperation ? null : operation ? (React.createElement("th", { style: Object.assign({}, thStyle, { width: operation.width || 150, right: 0, position: "sticky" }) }, operation.title)) : (React.createElement("th", { style: Object.assign({}, thStyle, { width: 150, right: 0, position: "sticky" }) }, i18n ? i18n.$t("global.operation") : "操作")))),
|
|
46
|
+
hideOperation ? null : operation ? (React.createElement("th", { style: Object.assign({}, thStyle, { width: operation.width || 150, right: 0, position: "sticky" }) }, operation.title)) : (React.createElement("th", { style: Object.assign({}, thStyle, { width: 150, right: 0, position: "sticky" }) }, i18n ? i18n.$t("global.operation", "操作") : "操作")))),
|
|
47
47
|
React.createElement("tbody", null, fields.map((field, index) => {
|
|
48
48
|
return (React.createElement("tr", { style: trStyle },
|
|
49
49
|
React.createElement("td", { style: tdStyle }, index + 1),
|
|
@@ -52,9 +52,9 @@ const C = ({ columns, rules, name, hideOperation, operation, i18n }) => {
|
|
|
52
52
|
React.createElement(Form.Item, { name: [field.name, column.name], rules: column.rules || [] }, column.render(field, index))));
|
|
53
53
|
}),
|
|
54
54
|
hideOperation ? null : operation ? (React.createElement("td", { style: Object.assign({}, tdStyle, { right: 0, position: "sticky", backgroundColor: "#fff" }) }, operation.component)) : (React.createElement("td", { style: Object.assign({}, tdStyle, { right: 0, position: "sticky", backgroundColor: "#fff" }) },
|
|
55
|
-
React.createElement(Typography.Text, { style: { cursor: 'pointer' }, type: "danger", onClick: () => remove(field.name) }, i18n ? i18n.$t("global.del") : '删除')))));
|
|
55
|
+
React.createElement(Typography.Text, { style: { cursor: 'pointer' }, type: "danger", onClick: () => remove(field.name) }, i18n ? i18n.$t("global.del", '删除') : '删除')))));
|
|
56
56
|
})))),
|
|
57
|
-
React.createElement("div", null,
|
|
58
|
-
React.createElement(Button, { icon: React.createElement(PlusCircleOutlined, null), type: "dashed", onClick: () => add() }, i18n ? i18n.$t("global.add") : "添加"))))));
|
|
57
|
+
hideBottom ? null : (React.createElement("div", null,
|
|
58
|
+
React.createElement(Button, { icon: React.createElement(PlusCircleOutlined, null), type: "dashed", onClick: () => add() }, i18n ? i18n.$t("global.add", "添加") : "添加")))))));
|
|
59
59
|
};
|
|
60
60
|
export default C;
|
|
@@ -10,7 +10,7 @@ export interface IModalProps {
|
|
|
10
10
|
mask?: boolean;
|
|
11
11
|
title?: React.ReactNode;
|
|
12
12
|
okDanger?: boolean;
|
|
13
|
-
okType?: "text" | "link" | "
|
|
13
|
+
okType?: "text" | "link" | "default" | "primary" | "dashed" | undefined;
|
|
14
14
|
okText?: string;
|
|
15
15
|
cancelText?: string;
|
|
16
16
|
closable?: boolean;
|
|
@@ -27,7 +27,7 @@ const InfosRender = ({ infos, setInfos }) => {
|
|
|
27
27
|
justifyContent: "space-between",
|
|
28
28
|
maxWidth: 250
|
|
29
29
|
} },
|
|
30
|
-
React.createElement(Typography.Link, { ellipsis: true, title: info.name, href: info.url, target: "_blank" },
|
|
30
|
+
React.createElement(Typography.Link, { download: info.name, ellipsis: true, title: info.name, href: info.url, target: "_blank" },
|
|
31
31
|
React.createElement(LinkOutlined, null),
|
|
32
32
|
" ",
|
|
33
33
|
info.name),
|
|
@@ -145,20 +145,20 @@ const ImgUpload = (props) => {
|
|
|
145
145
|
React.createElement("img", { style: { width: "102px", height: "102px", objectFit: "contain" }, src: imageUrl }))) : (uploadButton)),
|
|
146
146
|
React.createElement("div", null,
|
|
147
147
|
React.createElement("p", null,
|
|
148
|
-
props.i18n ? props.i18n.$t("global.size") : "大小",
|
|
148
|
+
props.i18n ? props.i18n.$t("global.size", "大小") : "大小",
|
|
149
149
|
"\uFF1A",
|
|
150
|
-
props.i18n ? props.i18n.$t("global.lt") : "小于",
|
|
150
|
+
props.i18n ? props.i18n.$t("global.lt", "小于") : "小于",
|
|
151
151
|
" ",
|
|
152
152
|
props.opts.size || 1,
|
|
153
153
|
"MB"),
|
|
154
154
|
React.createElement("p", null,
|
|
155
|
-
props.i18n ? props.i18n.$t("global.dimension") : "尺寸",
|
|
155
|
+
props.i18n ? props.i18n.$t("global.dimension", "尺寸") : "尺寸",
|
|
156
156
|
"\uFF1A",
|
|
157
157
|
props.opts.w ? `${props.opts.w}px` : "n",
|
|
158
158
|
" * ",
|
|
159
159
|
props.opts.h ? `${props.opts.h}px` : "n"),
|
|
160
160
|
React.createElement("p", null,
|
|
161
|
-
props.i18n ? props.i18n.$t("global.support") : "支持",
|
|
161
|
+
props.i18n ? props.i18n.$t("global.support", "支持") : "支持",
|
|
162
162
|
"\uFF1Ajpg\u3001jpeg\u3001png",
|
|
163
163
|
props.gif ? "、gif" : ""))));
|
|
164
164
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { default as SingleImgUpload } from "./core/single-img-upload";
|
|
|
13
13
|
export { default as SingleFileUpload } from "./core/single-file-upload";
|
|
14
14
|
export { default as MultipleUpload } from "./core/multiple-upload";
|
|
15
15
|
export { default as FormLabel } from "./core/form.label";
|
|
16
|
+
export { default as FormLabelAttachment } from "./core/form.label.attachment";
|
|
16
17
|
export { default as FormList } from "./core/form.list";
|
|
17
18
|
export { default as AsyncSelect } from "./core/async-select";
|
|
18
19
|
export { default as AsyncTransfer } from "./core/async-transfer";
|
package/lib/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export { default as SingleImgUpload } from "./core/single-img-upload";
|
|
|
13
13
|
export { default as SingleFileUpload } from "./core/single-file-upload";
|
|
14
14
|
export { default as MultipleUpload } from "./core/multiple-upload";
|
|
15
15
|
export { default as FormLabel } from "./core/form.label";
|
|
16
|
+
export { default as FormLabelAttachment } from "./core/form.label.attachment";
|
|
16
17
|
export { default as FormList } from "./core/form.list";
|
|
17
18
|
export { default as AsyncSelect } from "./core/async-select";
|
|
18
19
|
export { default as AsyncTransfer } from "./core/async-transfer";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecoding/components.antd",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.35",
|
|
4
4
|
"author": "cxc",
|
|
5
5
|
"homepage": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,11 +38,11 @@
|
|
|
38
38
|
"@ecoding/helper.json": "^0.0.5",
|
|
39
39
|
"@ecoding/helper.request.hook": "^0.0.6",
|
|
40
40
|
"@ecoding/helper.url": "^0.0.5",
|
|
41
|
-
"antd": "^5.
|
|
41
|
+
"antd": "^5.8.4",
|
|
42
42
|
"axios": "^1.1.2"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"react-quill": "^2.0.0"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "40f952fbe365c25cc90b04890feb2095ef4a56f7"
|
|
48
48
|
}
|