@zjlab-fe/data-hub-ui 0.32.6 → 0.33.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/dist/types/components/FileUploader/UploadStoreProvider/UploadStoreProvider.d.ts +4 -1
- package/dist/types/components/SDK-modal/document-link.d.ts +1 -3
- package/dist/types/components/SDK-modal/index.d.ts +4 -0
- package/dist/types/components/SDK-modal/inner-modal.d.ts +9 -0
- package/dist/types/components/SDK-modal/types.d.ts +4 -3
- package/dist/types/components/apply-perm-modal/index.d.ts +14 -5
- package/dist/types/components/confirm-again/index.d.ts +8 -1
- package/dist/types/components/copy/index.d.ts +9 -4
- package/dist/types/components/limit-credit-modal/index.d.ts +9 -3
- package/dist/types/components/tag-group-filter/dataSizeFilter.d.ts +0 -1
- package/dist/types/components/tag-group-filter/index.d.ts +4 -1
- package/dist/types/index.d.ts +7 -5
- package/dist/types/locale/index.d.ts +18 -0
- package/dist/types/locale/modalHolder.d.ts +11 -0
- package/dist/types/locale/resolveLocale.d.ts +9 -0
- package/dist/types/locale/translations.d.ts +808 -0
- package/dist/types/locale/types.d.ts +32 -0
- package/es/components/FileUploader/Locale/useTranslate.js +34 -11
- package/es/components/FileUploader/UploadStoreProvider/UploadStoreProvider.js +5 -3
- package/es/components/FileUploader/hooks/useOnMountedResumeUnfinished.js +6 -3
- package/es/components/SDK-modal/document-link.js +5 -2
- package/es/components/SDK-modal/index.js +29 -2
- package/es/components/SDK-modal/inner-modal.js +23 -12
- package/es/components/apply-perm-modal/index.js +20 -8
- package/es/components/confirm-again/index.js +12 -2
- package/es/components/copy/index.js +21 -7
- package/es/components/data-table/index.js +15 -4
- package/es/components/dataset-batch-action/index.js +48 -25
- package/es/components/file-preview/data-table/index.js +4 -3
- package/es/components/file-preview/index.js +5 -4
- package/es/components/file-uploader/components/uploader-drop-zone.js +4 -2
- package/es/components/file-uploader/components/uploader-file-item.js +12 -9
- package/es/components/file-uploader/components/uploader-file-list.js +6 -3
- package/es/components/file-uploader/components/uploader.js +4 -2
- package/es/components/file-uploader/components/uploading-status.js +18 -12
- package/es/components/header/index.js +3 -1
- package/es/components/input-tag/index.js +5 -2
- package/es/components/limit-credit-modal/index.js +38 -19
- package/es/components/menu/index.js +5 -2
- package/es/components/notion-editor/code-block/languages.js +1 -1
- package/es/components/notion-editor/index.js +34 -13
- package/es/components/operator-chain/components/AddButton.js +3 -1
- package/es/components/operator-chain/components/IOCard.js +4 -1
- package/es/components/operator-chain/components/VirtualDropdown.js +6 -3
- package/es/components/permission-editor/index.js +1 -0
- package/es/components/permission-editor/permissionEditModal/index.js +7 -4
- package/es/components/permission-editor/permissionEditor/index.js +40 -75
- package/es/components/permission-editor/permissionViewPopover/index.js +5 -2
- package/es/components/tag-group-filter/dataSizeFilter.js +6 -3
- package/es/components/tag-group-filter/index.js +2 -2
- package/es/components/tip-tap/bubble-menu.js +8 -3
- package/es/components/tip-tap/editor.js +5 -2
- package/es/components/tip-tap/extensions/index.js +1 -1
- package/es/components/tip-tap/toolbar/components/color-picker.js +3 -1
- package/es/components/tip-tap/toolbar/components/heading-dropdown.js +8 -5
- package/es/components/tip-tap/toolbar/components/link-button.js +4 -1
- package/es/components/tip-tap/toolbar/components/table-button.js +5 -2
- package/es/components/tip-tap/toolbar/index.js +4 -1
- package/es/components/uploadDrawer/fileUploadDrawer.js +6 -2
- package/es/components/uploadDrawer/fileUploadDrawerList.js +4 -1
- package/es/components/uploadDrawer/fileUploadDrawerListProgressButton.js +4 -2
- package/es/components/uploadDrawer/hooks/useCancelUpload.js +3 -1
- package/es/components/uploadDrawer/hooks/useFilterFiles.js +7 -4
- package/es/components/uploadDrawer/hooks/useFormatFiles.js +3 -1
- package/es/components/uploadDrawer/hooks/useResumeUnfinishedUploads.js +7 -6
- package/es/components/uploadDrawer/index.js +4 -2
- package/es/index.js +6 -5
- package/es/locale/index.js +64 -0
- package/es/locale/modalHolder.js +21 -0
- package/es/locale/resolveLocale.js +73 -0
- package/es/locale/translations.js +273 -0
- package/lib/index.js +1 -1
- package/package.json +7 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { translations } from './translations';
|
|
2
|
+
export type DataHubLang = 'zh' | 'en';
|
|
3
|
+
export type DataHubAntdMode = 'inherit' | 'isolated';
|
|
4
|
+
export type DataHubThemeToken = {
|
|
5
|
+
colorPrimary?: string;
|
|
6
|
+
colorSuccess?: string;
|
|
7
|
+
colorWarning?: string;
|
|
8
|
+
colorError?: string;
|
|
9
|
+
colorInfo?: string;
|
|
10
|
+
colorBgBase?: string;
|
|
11
|
+
colorTextBase?: string;
|
|
12
|
+
borderRadius?: number;
|
|
13
|
+
fontFamily?: string;
|
|
14
|
+
fontSize?: number;
|
|
15
|
+
motion?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export type DataHubTheme = {
|
|
18
|
+
token?: DataHubThemeToken;
|
|
19
|
+
darkMode?: boolean;
|
|
20
|
+
};
|
|
21
|
+
type MessageLeaf = {
|
|
22
|
+
zh: string;
|
|
23
|
+
en: string;
|
|
24
|
+
};
|
|
25
|
+
type ProjectedMessages<T> = T extends MessageLeaf ? string : T extends Record<string, unknown> ? {
|
|
26
|
+
[K in keyof T]: ProjectedMessages<T[K]>;
|
|
27
|
+
} : T;
|
|
28
|
+
export type DataHubLocaleMessages = ProjectedMessages<typeof translations>;
|
|
29
|
+
export type DataHubLocale = {
|
|
30
|
+
locale: DataHubLang;
|
|
31
|
+
} & DataHubLocaleMessages;
|
|
32
|
+
export {};
|
|
@@ -1,16 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FileUploaderLocaleContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
1
|
+
import { useLocale } from '../../../locale/index.js';
|
|
3
2
|
|
|
3
|
+
const LEGACY_KEY_MAP = {
|
|
4
|
+
'FileUploader 必须在 UploadStoreProvider 内使用': 'mustUseProvider',
|
|
5
|
+
'FileUploadModal 必须在 UploadStoreProvider 内使用': 'modalMustUseProvider',
|
|
6
|
+
文件上传: 'title',
|
|
7
|
+
确定: 'confirm',
|
|
8
|
+
等待上传: 'waiting',
|
|
9
|
+
已取消: 'cancelled',
|
|
10
|
+
上传中: 'uploading',
|
|
11
|
+
上传失败: 'failed',
|
|
12
|
+
已上传: 'uploaded',
|
|
13
|
+
分块合并中: 'mergingParts',
|
|
14
|
+
以下文件大小超过: 'sizeExceededPrefix',
|
|
15
|
+
已删除: 'deleted',
|
|
16
|
+
点击或拖拽上传文件: 'dropHint',
|
|
17
|
+
'发现同名文件,是否覆盖?': 'duplicateTitle',
|
|
18
|
+
覆盖: 'overwrite',
|
|
19
|
+
取消: 'cancel',
|
|
20
|
+
正在上传: 'uploadingNow',
|
|
21
|
+
取消失败: 'cancelFailed',
|
|
22
|
+
当前上传: 'currentUpload',
|
|
23
|
+
已暂停: 'paused',
|
|
24
|
+
上传成功: 'success',
|
|
25
|
+
校验中: 'calibrating',
|
|
26
|
+
合并中: 'merging',
|
|
27
|
+
部分文件获取上传地址失败: 'getUrlFailed',
|
|
28
|
+
};
|
|
4
29
|
function useTranslate() {
|
|
5
|
-
const locale =
|
|
6
|
-
return
|
|
7
|
-
const
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return content;
|
|
13
|
-
}, [locale]);
|
|
30
|
+
const { locale } = useLocale();
|
|
31
|
+
return (key) => {
|
|
32
|
+
const mapped = LEGACY_KEY_MAP[key];
|
|
33
|
+
if (mapped)
|
|
34
|
+
return locale.FileUploader[mapped];
|
|
35
|
+
return key;
|
|
36
|
+
};
|
|
14
37
|
}
|
|
15
38
|
|
|
16
39
|
export { useTranslate };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { createContext, useReducer, useState } from 'react';
|
|
3
3
|
import { useSaveUnfinishedUploads } from './useSaveUnfinishedUploads.js';
|
|
4
|
+
import { useLocale } from '../../../locale/index.js';
|
|
4
5
|
import { localeZh, localeEn } from '../Locale/translations.js';
|
|
5
6
|
import { useSetupMergingEvent } from './useSetupMergingEvent.js';
|
|
6
7
|
import { useOnFileAllUploaded } from './useOnFileAllUploaded.js';
|
|
@@ -17,15 +18,16 @@ const UploadStoreDispatchContext = createContext(() => null);
|
|
|
17
18
|
/**
|
|
18
19
|
* @deprecated This component is deprecated and will be removed in future releases.
|
|
19
20
|
*/
|
|
20
|
-
function UploadStoreProvider({ locale
|
|
21
|
-
const
|
|
21
|
+
function UploadStoreProvider({ locale: _locale, children, }) {
|
|
22
|
+
const { locale } = useLocale();
|
|
23
|
+
const fileUploaderLocale = locale.locale === 'en' ? localeEn : localeZh;
|
|
22
24
|
const [uploadStore, setUploadStore] = useReducer(uploadReducer, {});
|
|
23
25
|
const [allUploaderManagers, setAllUploaderManagers] = useState({});
|
|
24
26
|
const [allOnUploadSuccesses, setAllOnUploadSuccesses] = useState({});
|
|
25
27
|
useSaveUnfinishedUploads(uploadStore);
|
|
26
28
|
useOnFileAllUploaded(uploadStore, setUploadStore);
|
|
27
29
|
useSetupMergingEvent(uploadStore, allUploaderManagers, allOnUploadSuccesses, setUploadStore);
|
|
28
|
-
return (jsx(FileUploaderLocaleContext.Provider, { value:
|
|
30
|
+
return (jsx(FileUploaderLocaleContext.Provider, { value: fileUploaderLocale, children: jsx(AllUploaderManagersContext.Provider, { value: allUploaderManagers, children: jsx(AllUploaderManagersDispatchContext.Provider, { value: setAllUploaderManagers, children: jsx(AllOnUploadSuccessesContext.Provider, { value: allOnUploadSuccesses, children: jsx(AllOnUploadSuccessesDispatchContext.Provider, { value: setAllOnUploadSuccesses, children: jsx(UploadStoreContext.Provider, { value: uploadStore, children: jsx(UploadStoreDispatchContext.Provider, { value: setUploadStore, children: children }) }) }) }) }) }) }));
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export { AllOnUploadSuccessesContext, AllOnUploadSuccessesDispatchContext, AllUploaderManagersContext, AllUploaderManagersDispatchContext, FileUploaderLocaleContext, TEMP_STORE, UploadStoreContext, UploadStoreDispatchContext, UploadStoreProvider as default };
|
|
@@ -7,23 +7,26 @@ import { useContext, useCallback } from 'react';
|
|
|
7
7
|
import { useRetryUpload } from './useRetryUpload.js';
|
|
8
8
|
import { UploadStoreDispatchContext } from '../UploadStoreProvider/UploadStoreProvider.js';
|
|
9
9
|
import { confirmModalConfig } from '../utils/modalConfig.js';
|
|
10
|
+
import { useLocale } from '../../../locale/index.js';
|
|
10
11
|
|
|
11
12
|
function useOnMountedResumeUnfinished(identifier) {
|
|
12
13
|
const { message, modal } = App.useApp();
|
|
14
|
+
const { locale } = useLocale();
|
|
15
|
+
const texts = locale.FileUploader;
|
|
13
16
|
const setUploadStore = useContext(UploadStoreDispatchContext);
|
|
14
17
|
const retryUpload = useRetryUpload();
|
|
15
18
|
return useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
|
16
19
|
const prevUploadableFiles = yield reloadSaveData(identifier);
|
|
17
20
|
setUploadStore({ type: 'add_files', identifier, files: prevUploadableFiles });
|
|
18
21
|
if (prevUploadableFiles.length) {
|
|
19
|
-
modal.confirm(Object.assign(Object.assign({}, confirmModalConfig), { title:
|
|
22
|
+
modal.confirm(Object.assign(Object.assign({}, confirmModalConfig), { title: texts.notice, content: texts.unfinishedContent, onOk() {
|
|
20
23
|
prevUploadableFiles.forEach((file) => retryUpload(file));
|
|
21
24
|
},
|
|
22
25
|
onCancel() {
|
|
23
|
-
message.info(
|
|
26
|
+
message.info(texts.resumeManually);
|
|
24
27
|
} }));
|
|
25
28
|
}
|
|
26
|
-
}), [identifier, setUploadStore, retryUpload, modal, message]);
|
|
29
|
+
}), [identifier, setUploadStore, retryUpload, modal, message, texts]);
|
|
27
30
|
}
|
|
28
31
|
function reloadSaveData(identifier) {
|
|
29
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { documentLink, documentLinkAnchor } from './index.module.scss.js';
|
|
3
|
+
import { useLocale } from '../../locale/index.js';
|
|
3
4
|
|
|
4
|
-
function DocumentationLink({ link
|
|
5
|
-
|
|
5
|
+
function DocumentationLink({ link }) {
|
|
6
|
+
const { locale } = useLocale();
|
|
7
|
+
const texts = locale.SDKModal;
|
|
8
|
+
return (jsxs("span", { className: documentLink, children: [texts.documentPrefix, jsx("a", { href: link, target: "_blank", rel: "noopener noreferrer", className: documentLinkAnchor, children: texts.documentLinkText })] }));
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
export { DocumentationLink as default };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import InnerModal from './inner-modal.js';
|
|
3
|
+
import InnerModal, { defaultModalConfig, SDKModalContent } from './inner-modal.js';
|
|
4
|
+
import { useLocale } from '../../locale/index.js';
|
|
5
|
+
import { useDataHubModal } from '../../locale/modalHolder.js';
|
|
4
6
|
|
|
5
7
|
function showSDKModal(config) {
|
|
6
8
|
const container = document.createElement('div');
|
|
@@ -16,10 +18,35 @@ function showSDKModal(config) {
|
|
|
16
18
|
root.render(jsx(InnerModal, { open: true, onClose: destroy, SDKCode: config.SDKCode, loadSDK: config.loadSDK, title: config.title, subTitle: config.subTitle, modalConfig: config.modalConfig, documentLink: config.documentLink, locale: config.locale }));
|
|
17
19
|
return { destroy };
|
|
18
20
|
}
|
|
21
|
+
function useSDKModal() {
|
|
22
|
+
const { locale } = useLocale();
|
|
23
|
+
const modal = useDataHubModal();
|
|
24
|
+
const sdkTexts = locale.SDKModal;
|
|
25
|
+
return (config) => {
|
|
26
|
+
var _a, _b, _c, _d, _e;
|
|
27
|
+
const modalConfig = (_a = config.modalConfig) !== null && _a !== void 0 ? _a : {};
|
|
28
|
+
const widthCandidate = (_b = modalConfig.width) !== null && _b !== void 0 ? _b : defaultModalConfig.width;
|
|
29
|
+
const width = typeof widthCandidate === 'number' || typeof widthCandidate === 'string' ? widthCandidate : 600;
|
|
30
|
+
return modal.confirm({
|
|
31
|
+
title: config.title,
|
|
32
|
+
content: (jsx(SDKModalContent, { SDKCode: config.SDKCode, loadSDK: config.loadSDK, subTitle: config.subTitle, documentLink: config.documentLink })),
|
|
33
|
+
icon: null,
|
|
34
|
+
okCancel: false,
|
|
35
|
+
okText: sdkTexts.confirm,
|
|
36
|
+
width,
|
|
37
|
+
centered: (_c = modalConfig.centered) !== null && _c !== void 0 ? _c : defaultModalConfig.centered,
|
|
38
|
+
closable: (_d = modalConfig.closable) !== null && _d !== void 0 ? _d : defaultModalConfig.closable,
|
|
39
|
+
styles: (_e = modalConfig.styles) !== null && _e !== void 0 ? _e : defaultModalConfig.styles,
|
|
40
|
+
onOk: () => { var _a; return (_a = config.onClose) === null || _a === void 0 ? void 0 : _a.call(config); },
|
|
41
|
+
onCancel: () => { var _a; return (_a = config.onClose) === null || _a === void 0 ? void 0 : _a.call(config); },
|
|
42
|
+
footer: (_originNode, { OkBtn }) => (jsx("div", { style: { textAlign: 'center' }, children: jsx(OkBtn, {}) })),
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
}
|
|
19
46
|
function SDKModalComponent(props) {
|
|
20
47
|
return jsx(InnerModal, Object.assign({}, props));
|
|
21
48
|
}
|
|
22
49
|
const SDKModal = SDKModalComponent;
|
|
23
50
|
SDKModal.show = showSDKModal;
|
|
24
51
|
|
|
25
|
-
export { SDKModal as default, showSDKModal };
|
|
52
|
+
export { SDKModal as default, showSDKModal, useSDKModal };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { jsxs,
|
|
2
|
-
import {
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Spin, Flex, Modal, Button } from 'antd';
|
|
3
3
|
import { memo, useState, useEffect } from 'react';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import Copy from '../copy/index.js';
|
|
6
6
|
import DocumentationLink from './document-link.js';
|
|
7
|
-
import { getLocale } from './locale/translations.js';
|
|
8
7
|
import { codeBlock, loading, errorText, codeContent } from './index.module.scss.js';
|
|
8
|
+
import { useLocale } from '../../locale/index.js';
|
|
9
9
|
|
|
10
10
|
const defaultModalConfig = {
|
|
11
11
|
width: 600,
|
|
@@ -19,13 +19,13 @@ const defaultModalConfig = {
|
|
|
19
19
|
content: { padding: '20px 20px 16px 20px', borderRadius: '10px' },
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
|
-
|
|
22
|
+
const SDKModalContent = memo(function SDKModalContent({ SDKCode, loadSDK, subTitle, documentLink, active = true, }) {
|
|
23
23
|
const [code, setCode] = useState('');
|
|
24
24
|
const [loading$1, setLoading] = useState(false);
|
|
25
25
|
const [error, setError] = useState('');
|
|
26
|
-
const resolvedLocale = getLocale(locale);
|
|
27
26
|
useEffect(() => {
|
|
28
|
-
|
|
27
|
+
let requestActive = true;
|
|
28
|
+
if (!active) {
|
|
29
29
|
setCode('');
|
|
30
30
|
setError('');
|
|
31
31
|
setLoading(false);
|
|
@@ -41,19 +41,30 @@ var InnerModal = memo(function InnerModal({ open, onClose, SDKCode, loadSDK, tit
|
|
|
41
41
|
setLoading(true);
|
|
42
42
|
loadSDK()
|
|
43
43
|
.then((result) => {
|
|
44
|
-
|
|
44
|
+
if (requestActive)
|
|
45
|
+
setCode(result);
|
|
45
46
|
})
|
|
46
47
|
.catch((err) => {
|
|
47
48
|
var _a;
|
|
48
|
-
|
|
49
|
+
if (requestActive)
|
|
50
|
+
setError((_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : String(err));
|
|
49
51
|
})
|
|
50
52
|
.finally(() => {
|
|
51
|
-
|
|
53
|
+
if (requestActive)
|
|
54
|
+
setLoading(false);
|
|
52
55
|
});
|
|
53
56
|
}
|
|
54
|
-
|
|
57
|
+
return () => {
|
|
58
|
+
requestActive = false;
|
|
59
|
+
};
|
|
60
|
+
}, [active, SDKCode, loadSDK]);
|
|
61
|
+
return (jsxs(Fragment, { children: [subTitle && jsx("div", { children: subTitle }), jsx(Spin, { spinning: loading$1, className: classNames(codeBlock, loading) }), !loading$1 && (jsx(Flex, { align: "start", justify: "space-between", className: codeBlock, children: error ? (jsx("span", { className: errorText, children: error })) : (jsxs(Fragment, { children: [jsx("div", { className: codeContent, dangerouslySetInnerHTML: { __html: code.replace(/\n/g, '<br>') } }), jsx(Copy, { text: code, showFeedback: true })] })) })), documentLink && jsx(DocumentationLink, { link: documentLink })] }));
|
|
62
|
+
});
|
|
63
|
+
var InnerModal = memo(function InnerModal({ open, onClose, SDKCode, loadSDK, title, subTitle, modalConfig, documentLink, locale: _locale, }) {
|
|
64
|
+
const { locale } = useLocale();
|
|
65
|
+
const texts = locale.SDKModal;
|
|
55
66
|
const mergedConfig = Object.assign(Object.assign({}, defaultModalConfig), modalConfig);
|
|
56
|
-
return (
|
|
67
|
+
return (jsx(Modal, Object.assign({}, mergedConfig, { open: open, title: title, onCancel: onClose, footer: jsx(Button, { type: "primary", onClick: onClose, children: texts.confirm }), children: jsx(SDKModalContent, { active: open, SDKCode: SDKCode, loadSDK: loadSDK, subTitle: subTitle, documentLink: documentLink }) })));
|
|
57
68
|
});
|
|
58
69
|
|
|
59
|
-
export { InnerModal as default };
|
|
70
|
+
export { SDKModalContent, InnerModal as default, defaultModalConfig };
|
|
@@ -2,6 +2,8 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { Flex, Button, Modal } from 'antd';
|
|
3
3
|
import { noModalWrap, title, content, footer, permModal, permFunModal } from './index.module.scss.js';
|
|
4
4
|
import { isPublicNetwork } from '@zjlab-fe/util';
|
|
5
|
+
import { useLocale } from '../../locale/index.js';
|
|
6
|
+
import { useDataHubModal } from '../../locale/modalHolder.js';
|
|
5
7
|
|
|
6
8
|
const okText = {
|
|
7
9
|
zh: '申请',
|
|
@@ -24,30 +26,40 @@ const applyUrl = (isPublic) => isPublic
|
|
|
24
26
|
: 'https://alidocs.dingtalk.com/notable/share/form/v01Q35O8510LgZgBl9V_dv19yqvsgs3oebp3pcjys_1qX0QQ0';
|
|
25
27
|
/**
|
|
26
28
|
* 申请权限弹窗
|
|
27
|
-
* @param locale
|
|
29
|
+
* @param locale 已废弃,语言由 DataHubProvider / antd ConfigProvider 决定
|
|
28
30
|
* @param open {boolean} 是否展示弹窗
|
|
29
31
|
* @param noModal {boolean} 是否以非弹窗形式展示
|
|
30
32
|
* @param onCancel {function} 取消回调
|
|
31
|
-
* @returns
|
|
32
33
|
*/
|
|
33
34
|
function ApplyPermModal(props) {
|
|
34
|
-
const {
|
|
35
|
+
const { noModal = false } = props;
|
|
36
|
+
const { locale } = useLocale();
|
|
37
|
+
const lang = locale.locale;
|
|
35
38
|
const handleApply = () => window.open(applyUrl(isPublicNetwork()), '_blank');
|
|
36
39
|
if (noModal) {
|
|
37
|
-
return (jsxs(Flex, { vertical: true, align: "center", gap: 8, className: noModalWrap, children: [jsx("div", { className: title, children: titleText[
|
|
40
|
+
return (jsxs(Flex, { vertical: true, align: "center", gap: 8, className: noModalWrap, children: [jsx("div", { className: title, children: titleText[lang] }), jsx("div", { className: content, children: contentText[lang] }), jsx(Flex, { className: footer, children: jsx(Button, { type: "primary", onClick: handleApply, children: okText[lang] }) })] }));
|
|
38
41
|
}
|
|
39
|
-
return (jsx(Modal, Object.assign({}, props, { title: titleText[
|
|
42
|
+
return (jsx(Modal, Object.assign({}, props, { title: titleText[lang], onOk: handleApply, okText: okText[lang], cancelText: cancelText[lang], wrapClassName: permModal, width: 400, children: contentText[lang] })));
|
|
40
43
|
}
|
|
41
44
|
ApplyPermModal.confirm = (props) => {
|
|
42
|
-
const { locale = 'zh' } = props || {};
|
|
43
45
|
const handleApply = () => window.open(applyUrl(isPublicNetwork()), '_blank');
|
|
44
|
-
const modal = Modal.confirm(Object.assign(Object.assign({}, props), { open: true, title: titleText
|
|
46
|
+
const modal = Modal.confirm(Object.assign(Object.assign({}, props), { open: true, title: titleText.zh, content: contentText.zh, onOk: handleApply, okText: okText.zh, cancelText: cancelText.zh }));
|
|
45
47
|
modal.update({
|
|
46
48
|
icon: null,
|
|
47
49
|
closable: true,
|
|
48
50
|
width: 400,
|
|
49
51
|
wrapClassName: `${permFunModal}`,
|
|
50
52
|
});
|
|
53
|
+
return modal;
|
|
51
54
|
};
|
|
55
|
+
function useApplyPermModal() {
|
|
56
|
+
const { locale } = useLocale();
|
|
57
|
+
const modal = useDataHubModal();
|
|
58
|
+
const lang = locale.locale;
|
|
59
|
+
return (props) => {
|
|
60
|
+
const handleApply = () => window.open(applyUrl(isPublicNetwork()), '_blank');
|
|
61
|
+
return modal.confirm(Object.assign(Object.assign({}, props), { open: true, title: titleText[lang], content: contentText[lang], onOk: handleApply, okText: okText[lang], cancelText: cancelText[lang], icon: null, closable: true, width: 400, wrapClassName: permFunModal }));
|
|
62
|
+
};
|
|
63
|
+
}
|
|
52
64
|
|
|
53
|
-
export { ApplyPermModal as default };
|
|
65
|
+
export { ApplyPermModal as default, useApplyPermModal };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { Modal } from 'antd';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
|
+
import { useLocale } from '../../locale/index.js';
|
|
5
|
+
import { useDataHubModal } from '../../locale/modalHolder.js';
|
|
4
6
|
import useStyle from './index.scss.js';
|
|
5
7
|
|
|
6
8
|
useStyle();
|
|
@@ -10,7 +12,15 @@ function ConfirmAgain(props) {
|
|
|
10
12
|
}
|
|
11
13
|
ConfirmAgain.confirm = (props) => {
|
|
12
14
|
var _a, _b, _c;
|
|
13
|
-
Modal.confirm(Object.assign(Object.assign({}, props), { width: (_a = props.width) !== null && _a !== void 0 ? _a : 400, closable: (_b = props.closable) !== null && _b !== void 0 ? _b : true, icon: (_c = props.icon) !== null && _c !== void 0 ? _c : null, wrapClassName: classNames('data-hub-ui-confirm-wrap', props.wrapClassName) }));
|
|
15
|
+
return Modal.confirm(Object.assign(Object.assign({}, props), { width: (_a = props.width) !== null && _a !== void 0 ? _a : 400, closable: (_b = props.closable) !== null && _b !== void 0 ? _b : true, icon: (_c = props.icon) !== null && _c !== void 0 ? _c : null, wrapClassName: classNames('data-hub-ui-confirm-wrap', props.wrapClassName) }));
|
|
14
16
|
};
|
|
17
|
+
function useConfirmAgain() {
|
|
18
|
+
const { locale } = useLocale();
|
|
19
|
+
const modal = useDataHubModal();
|
|
20
|
+
return (props) => {
|
|
21
|
+
var _a, _b, _c, _d, _e;
|
|
22
|
+
return modal.confirm(Object.assign(Object.assign({}, props), { width: (_a = props.width) !== null && _a !== void 0 ? _a : 400, closable: (_b = props.closable) !== null && _b !== void 0 ? _b : true, icon: (_c = props.icon) !== null && _c !== void 0 ? _c : null, okText: (_d = props.okText) !== null && _d !== void 0 ? _d : locale.Common.confirm, cancelText: (_e = props.cancelText) !== null && _e !== void 0 ? _e : locale.Common.cancel, wrapClassName: classNames('data-hub-ui-confirm-wrap', props.wrapClassName) }));
|
|
23
|
+
};
|
|
24
|
+
}
|
|
15
25
|
|
|
16
|
-
export { ConfirmAgain as default };
|
|
26
|
+
export { ConfirmAgain as default, useConfirmAgain };
|
|
@@ -3,39 +3,53 @@ import { message } from 'antd';
|
|
|
3
3
|
import copyToClipboard from 'copy-to-clipboard';
|
|
4
4
|
import { icon } from './index.module.scss.js';
|
|
5
5
|
import classNames from 'classnames';
|
|
6
|
+
import { useLocale } from '../../locale/index.js';
|
|
6
7
|
|
|
7
8
|
const successMsg = {
|
|
8
9
|
zh: '已复制',
|
|
9
10
|
en: 'Copied',
|
|
10
11
|
};
|
|
11
12
|
function Copy(props) {
|
|
12
|
-
const { showFeedback = true, text
|
|
13
|
+
const { showFeedback = true, text } = props;
|
|
14
|
+
const { locale } = useLocale();
|
|
13
15
|
const onClick = () => {
|
|
14
16
|
if (text) {
|
|
15
17
|
copyToClipboard(text);
|
|
16
18
|
if (showFeedback) {
|
|
17
|
-
message.success(successMsg[locale]);
|
|
19
|
+
message.success(successMsg[locale.locale]);
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
(props === null || props === void 0 ? void 0 : props.onClick) && props.onClick();
|
|
21
23
|
};
|
|
22
24
|
return (jsx("span", { className: classNames(icon, 'data-hub-ui-copy-icon'), onClick: onClick, children: "\uE85C" }));
|
|
23
25
|
}
|
|
26
|
+
function useCopy() {
|
|
27
|
+
const { locale } = useLocale();
|
|
28
|
+
return (text, options = { showFeedback: true }) => {
|
|
29
|
+
const { showFeedback = true } = options;
|
|
30
|
+
if (text) {
|
|
31
|
+
copyToClipboard(text);
|
|
32
|
+
if (showFeedback) {
|
|
33
|
+
message.success(successMsg[locale.locale]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
24
38
|
/**
|
|
25
39
|
* 复制文本内容到粘贴板
|
|
26
40
|
* @param text {string} 文本内容
|
|
27
41
|
* @param options {object} 其它选项
|
|
28
42
|
* @param options.showFeedback {boolean} 是否展示复制成功的反馈信息,默认展示
|
|
29
|
-
* @param options.locale
|
|
43
|
+
* @param options.locale 已废弃,语言由 DataHubProvider / antd ConfigProvider 决定
|
|
30
44
|
*/
|
|
31
|
-
function copy(text, options = { showFeedback: true
|
|
32
|
-
const { showFeedback =
|
|
45
|
+
function copy(text, options = { showFeedback: true }) {
|
|
46
|
+
const { showFeedback = true } = options;
|
|
33
47
|
if (text) {
|
|
34
48
|
copyToClipboard(text);
|
|
35
49
|
if (showFeedback) {
|
|
36
|
-
message.success(successMsg
|
|
50
|
+
message.success(successMsg.zh);
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
}
|
|
40
54
|
|
|
41
|
-
export { copy, Copy as default };
|
|
55
|
+
export { copy, Copy as default, useCopy };
|
|
@@ -3,6 +3,7 @@ import React from 'react';
|
|
|
3
3
|
import { Table, Empty } from 'antd';
|
|
4
4
|
import ActionCell from './action-cell.js';
|
|
5
5
|
import { dataTable, dataTableRowClickable, truncateText, truncateTextExpanded } from './index.module.scss.js';
|
|
6
|
+
import { useLocale } from '../../locale/index.js';
|
|
6
7
|
|
|
7
8
|
const DEFAULT_MIN_WIDTH = 920;
|
|
8
9
|
const DEFAULT_EXPAND_MAX_HEIGHT = 200;
|
|
@@ -47,7 +48,9 @@ function TruncateText({ content, expanded, title, }) {
|
|
|
47
48
|
}
|
|
48
49
|
function DataTable(props) {
|
|
49
50
|
var _a, _b;
|
|
50
|
-
const { rowKey, columns, actions, actionColumnTitle
|
|
51
|
+
const { rowKey, columns, actions, actionColumnTitle, actionColumnWidth = 188, dataSource, loading = false, pagination: controlledPagination, onChange, rowSelection, defaultPageSize = 10, showSizeChanger = false, showQuickJumper = true, className, minWidth = DEFAULT_MIN_WIDTH, rowTextExpand, } = props;
|
|
52
|
+
const { locale } = useLocale();
|
|
53
|
+
const resolvedActionColumnTitle = actionColumnTitle !== null && actionColumnTitle !== void 0 ? actionColumnTitle : locale.DataTable.action;
|
|
51
54
|
const expandEnabled = Boolean(rowTextExpand);
|
|
52
55
|
const expandMultiple = typeof rowTextExpand === 'object' ? ((_a = rowTextExpand.multiple) !== null && _a !== void 0 ? _a : true) : true;
|
|
53
56
|
const expandMaxHeight = typeof rowTextExpand === 'object'
|
|
@@ -106,12 +109,20 @@ function DataTable(props) {
|
|
|
106
109
|
...enhancedColumns,
|
|
107
110
|
{
|
|
108
111
|
key: '__actions__',
|
|
109
|
-
title:
|
|
112
|
+
title: resolvedActionColumnTitle,
|
|
110
113
|
width: actionColumnWidth,
|
|
111
114
|
render: (_, record) => jsx(ActionCell, { record: record, actions: actions }),
|
|
112
115
|
},
|
|
113
116
|
];
|
|
114
|
-
}, [
|
|
117
|
+
}, [
|
|
118
|
+
actions,
|
|
119
|
+
resolvedActionColumnTitle,
|
|
120
|
+
actionColumnWidth,
|
|
121
|
+
columns,
|
|
122
|
+
expandEnabled,
|
|
123
|
+
expandedRowKeys,
|
|
124
|
+
rowKey,
|
|
125
|
+
]);
|
|
115
126
|
const resolvedRowSelection = React.useMemo(() => {
|
|
116
127
|
var _a;
|
|
117
128
|
if (!rowSelection) {
|
|
@@ -159,7 +170,7 @@ function DataTable(props) {
|
|
|
159
170
|
},
|
|
160
171
|
})
|
|
161
172
|
: undefined, locale: {
|
|
162
|
-
emptyText: jsx(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE, description:
|
|
173
|
+
emptyText: jsx(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE, description: locale.DataTable.empty }),
|
|
163
174
|
} }));
|
|
164
175
|
}
|
|
165
176
|
|
|
@@ -2,6 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Upload, Input, Modal, Tabs, message, Alert, Button } from 'antd';
|
|
4
4
|
import { datasetBatchAction, description, manualLabel, uploadContainer, uploadIconWrapper, uploadIcon, uploadText, alertMessage, fieldSelection, fieldHeader, fieldTitleWrapper, fieldTitleIndicator, fieldTitle, fieldActions, selectAllBtn, clearAllBtn, fieldGrid, fieldItem, selected, unselected, fieldItemContent, fieldLabel, fieldCheckbox, checked, unchecked, checkIcon, fieldMeta, listTip, tipContent, tipIcon, tipText } from './index.module.scss.js';
|
|
5
|
+
import { useLocale } from '../../locale/index.js';
|
|
5
6
|
|
|
6
7
|
const { Dragger } = Upload;
|
|
7
8
|
const { TextArea } = Input;
|
|
@@ -12,39 +13,61 @@ var EDatasetBatchType;
|
|
|
12
13
|
EDatasetBatchType["tag"] = "tag";
|
|
13
14
|
EDatasetBatchType["zone"] = "area";
|
|
14
15
|
})(EDatasetBatchType || (EDatasetBatchType = {}));
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
const DATASET_FIELD_IDS = [
|
|
17
|
+
'id',
|
|
18
|
+
'name',
|
|
19
|
+
'provider',
|
|
20
|
+
'creator',
|
|
21
|
+
'fileSize',
|
|
22
|
+
'authorizationType',
|
|
23
|
+
'subjects',
|
|
24
|
+
'source',
|
|
25
|
+
'keywords',
|
|
26
|
+
'label',
|
|
27
|
+
'license',
|
|
28
|
+
'dataSourceUrl',
|
|
29
|
+
'publishTime',
|
|
30
|
+
'storageFilePath',
|
|
31
|
+
'domain',
|
|
31
32
|
];
|
|
33
|
+
function getDatasetFields(texts) {
|
|
34
|
+
const labels = {
|
|
35
|
+
id: texts.fieldId,
|
|
36
|
+
name: texts.fieldName,
|
|
37
|
+
provider: texts.fieldProvider,
|
|
38
|
+
creator: texts.fieldCreator,
|
|
39
|
+
fileSize: texts.fieldFileSize,
|
|
40
|
+
authorizationType: texts.fieldAuthorizationType,
|
|
41
|
+
subjects: texts.fieldSubjects,
|
|
42
|
+
source: texts.fieldSource,
|
|
43
|
+
keywords: texts.fieldKeywords,
|
|
44
|
+
label: texts.fieldLabel,
|
|
45
|
+
license: texts.fieldLicense,
|
|
46
|
+
dataSourceUrl: texts.fieldDataSourceUrl,
|
|
47
|
+
publishTime: texts.fieldPublishTime,
|
|
48
|
+
storageFilePath: texts.fieldStorageFilePath,
|
|
49
|
+
domain: texts.fieldDomain,
|
|
50
|
+
};
|
|
51
|
+
return DATASET_FIELD_IDS.map((id) => ({ id, label: labels[id] }));
|
|
52
|
+
}
|
|
32
53
|
function DatasetBatchAction(p) {
|
|
33
54
|
var _a, _b;
|
|
55
|
+
const { locale } = useLocale();
|
|
56
|
+
const texts = locale.DatasetBatchAction;
|
|
34
57
|
const [fileList, setFileList] = React.useState([]);
|
|
35
58
|
const [manualInputValue, setManualInputValue] = React.useState('');
|
|
36
59
|
const [activeTab, setActiveTab] = React.useState(p.hasZoneManualInput ? 'manual' : 'upload');
|
|
37
|
-
const exportFields = (_a = p.fieldOptions) !== null && _a !== void 0 ? _a : (p.type === EDatasetBatchType.list || p.type === EDatasetBatchType.export ?
|
|
60
|
+
const exportFields = (_a = p.fieldOptions) !== null && _a !== void 0 ? _a : (p.type === EDatasetBatchType.list || p.type === EDatasetBatchType.export ? getDatasetFields(texts) : []);
|
|
38
61
|
const [selectedFields, setSelectedFields] = React.useState(new Set((exportFields === null || exportFields === void 0 ? void 0 : exportFields.map((f) => f.id)) || []));
|
|
39
62
|
const hasUpload = (_b = p.hasUpload) !== null && _b !== void 0 ? _b : true;
|
|
40
63
|
const handleConfirmExport = () => {
|
|
41
64
|
if (p.type === EDatasetBatchType.zone) {
|
|
42
65
|
if (activeTab === 'manual' && !manualInputValue.trim()) {
|
|
43
|
-
message.warning(
|
|
66
|
+
message.warning(texts.enterDatasetId);
|
|
44
67
|
return;
|
|
45
68
|
}
|
|
46
69
|
if (activeTab === 'upload' && !fileList.length) {
|
|
47
|
-
message.warning(
|
|
70
|
+
message.warning(texts.uploadCsv);
|
|
48
71
|
return;
|
|
49
72
|
}
|
|
50
73
|
const inputIds = activeTab === 'manual'
|
|
@@ -61,7 +84,7 @@ function DatasetBatchAction(p) {
|
|
|
61
84
|
});
|
|
62
85
|
}
|
|
63
86
|
else if (p.type !== EDatasetBatchType.list && !fileList.length) {
|
|
64
|
-
message.warning(
|
|
87
|
+
message.warning(texts.uploadCsvOrExcel);
|
|
65
88
|
return;
|
|
66
89
|
}
|
|
67
90
|
else {
|
|
@@ -76,14 +99,14 @@ function DatasetBatchAction(p) {
|
|
|
76
99
|
next.add(fieldId);
|
|
77
100
|
setSelectedFields(next);
|
|
78
101
|
};
|
|
79
|
-
return (jsxs(Modal, { title: p.title, open: true, onOk: handleConfirmExport, onCancel: p.onCancel, className: datasetBatchAction, okText:
|
|
102
|
+
return (jsxs(Modal, { title: p.title, open: true, onOk: handleConfirmExport, onCancel: p.onCancel, className: datasetBatchAction, okText: texts.ok, cancelText: texts.cancel, children: [jsx("p", { className: description, children: p.description }), p.type === EDatasetBatchType.zone && p.hasZoneManualInput && (jsxs(Fragment, { children: [hasUpload && (jsx(Tabs, { activeKey: activeTab, onChange: setActiveTab, items: [
|
|
80
103
|
{
|
|
81
104
|
key: 'manual',
|
|
82
|
-
label:
|
|
105
|
+
label: texts.manualTab,
|
|
83
106
|
},
|
|
84
107
|
{
|
|
85
108
|
key: 'upload',
|
|
86
|
-
label:
|
|
109
|
+
label: texts.uploadTab,
|
|
87
110
|
},
|
|
88
111
|
] })), activeTab === 'manual' && (jsxs("div", { children: [jsx("p", { className: manualLabel, children: p.manualInputTitle }), jsx(TextArea, { value: manualInputValue, onChange: (e) => setManualInputValue(e.target.value), placeholder: p.manualInputPlaceholder, rows: 6 })] }))] })), hasUpload &&
|
|
89
112
|
(p.type === EDatasetBatchType.export ||
|
|
@@ -95,10 +118,10 @@ function DatasetBatchAction(p) {
|
|
|
95
118
|
}, className: uploadContainer, multiple: false, accept: ".csv,.xlsx,.xls", fileList: fileList, onChange: (info) => {
|
|
96
119
|
const newFileList = [...info.fileList];
|
|
97
120
|
if (newFileList.length > 1) {
|
|
98
|
-
message.warning(
|
|
121
|
+
message.warning(texts.onlyOneFile);
|
|
99
122
|
}
|
|
100
123
|
setFileList(newFileList.slice(0, 1));
|
|
101
|
-
}, onRemove: () => setFileList([]), children: [jsx("div", { className: uploadIconWrapper, children: jsx("svg", { className: uploadIcon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }) }), jsx("div", { className: uploadText, children:
|
|
124
|
+
}, onRemove: () => setFileList([]), children: [jsx("div", { className: uploadIconWrapper, children: jsx("svg", { className: uploadIcon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" }) }) }), jsx("div", { className: uploadText, children: texts.dragUpload })] })), p.type === EDatasetBatchType.tag && (jsx(Alert, { message: texts.tagAlert, type: "info", showIcon: true, className: alertMessage })), p.type === EDatasetBatchType.zone && activeTab === 'upload' && p.hasZoneManualInput && (jsx(Alert, { message: texts.zoneAlert, type: "info", showIcon: true, className: alertMessage })), exportFields && exportFields.length > 0 && (jsxs("div", { className: fieldSelection, children: [jsxs("div", { className: fieldHeader, children: [jsxs("div", { className: fieldTitleWrapper, children: [jsx("div", { className: fieldTitleIndicator }), jsx("h4", { className: fieldTitle, children: p.fieldTitle })] }), jsxs("div", { className: fieldActions, children: [jsx("span", { onClick: () => setSelectedFields(new Set((exportFields === null || exportFields === void 0 ? void 0 : exportFields.map((f) => f.id)) || [])), className: selectAllBtn, children: "\u5168\u9009" }), jsx("span", { onClick: () => setSelectedFields(new Set()), className: clearAllBtn, children: "\u6E05\u7A7A" })] })] }), jsx("div", { className: fieldGrid, children: exportFields.map((field) => {
|
|
102
125
|
const isSelected = selectedFields.has(field.id);
|
|
103
126
|
return (jsxs(Button, { onClick: () => toggleExportField(field.id), className: `${fieldItem} ${isSelected ? selected : unselected}`, style: { height: p.type === EDatasetBatchType.zone ? '60px' : '32px' }, children: [jsxs("div", { className: fieldItemContent, children: [jsx("span", { className: fieldLabel, title: field.label, children: field.label }), jsx("div", { className: `${fieldCheckbox} ${isSelected ? checked : unchecked}`, children: isSelected && (jsx("svg", { className: checkIcon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 4, children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) })) })] }), p.type === EDatasetBatchType.zone && (jsxs("div", { className: fieldMeta, children: [jsxs("span", { children: ["ID\uFF1A", field.id] }), jsxs("span", { children: [field.datasetCnt, " \u8D44\u4EA7"] })] }))] }, field.id));
|
|
104
127
|
}) })] })), p.type === EDatasetBatchType.list && (jsx("div", { className: listTip, children: jsxs("div", { className: tipContent, children: [jsx("svg", { className: tipIcon, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), jsx("p", { className: tipText, children: "\u8BF7\u524D\u5F80\"\u6279\u91CF\u4EFB\u52A1\"\u4E2D\u67E5\u770B\u5BFC\u51FA\u6587\u4EF6" })] }) }))] }));
|