mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-11-29 18:58:26 +08:00
refactor: rewrite the UI of the code scanner. (#4677)
* feat: workbench block * feat: mobilePage * fix: update WorkbenchAction * feat: support qrcode embed in markdown and scan in mobile * fix: fix markdown button be covered problem * fix: fix unit test error * fix: fix unit test errors * refactor: use react router in qrcode scanner * feat: markdown add loading * fix: fix blank content in print page * refactor: change plugin dependencies to devDependencies * feat: add some padding in markdown editor * chore: improve some code * feat: improve code * fix: add QRCodeScanner * fix: iconColor * fix: Improve code * feat: Improve code * fix: version * chore: improve some code * chore: improve some code * fix: i18n * refactor: refact the UI of code scanner * feat: add some locale * feat: add qrbox * feat: add image upload and fix qrbox * feat: fix full screen problem * fix: fix not full screen problem * fix: add some error handling * feat: add album locale --------- Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
86a56ef7cc
commit
ba1cdce6e9
@ -2,9 +2,7 @@
|
||||
"version": "1.2.11-alpha",
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
"npmClientArgs": [
|
||||
"--ignore-engines"
|
||||
],
|
||||
"npmClientArgs": ["--ignore-engines"],
|
||||
"command": {
|
||||
"version": {
|
||||
"forcePublish": true,
|
||||
|
@ -12,6 +12,8 @@
|
||||
"@nocobase/test": "1.x"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ant-design/icons": "^5.x",
|
||||
"antd": "^5.x",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"react-router-dom": "^6.x"
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ const InternalIcons = () => {
|
||||
<DndContext>
|
||||
<Space wrap>
|
||||
{fieldSchema.mapProperties((s, key) => (
|
||||
<RecursionField name={key} schema={s} />
|
||||
<RecursionField name={key} schema={s} key={key} />
|
||||
))}
|
||||
</Space>
|
||||
</DndContext>
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
ButtonEditor,
|
||||
ISchema,
|
||||
SchemaSettings,
|
||||
useActionContext,
|
||||
useSchemaInitializer,
|
||||
useSchemaInitializerItem,
|
||||
} from '@nocobase/client';
|
||||
@ -45,14 +44,6 @@ export function WorkbenchScanActionSchemaInitializerItem(props) {
|
||||
// 调用插入功能
|
||||
const { insert } = useSchemaInitializer();
|
||||
const { t } = useTranslation();
|
||||
const useCancelAction = () => {
|
||||
const { setVisible } = useActionContext();
|
||||
return {
|
||||
run() {
|
||||
setVisible(false);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalActionSchemaInitializerItem
|
||||
@ -96,33 +87,8 @@ export function WorkbenchScanActionSchemaInitializerItem(props) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Modal',
|
||||
title: t('Scan QR code', { ns: 'block-workbench' }),
|
||||
'x-decorator': 'FormV2',
|
||||
properties: {
|
||||
scanner: {
|
||||
'x-component': 'QRCodeScanner',
|
||||
'x-component-props': {
|
||||
fps: 10,
|
||||
qrbox: 250,
|
||||
disableFlip: false,
|
||||
},
|
||||
},
|
||||
footer: {
|
||||
type: 'void',
|
||||
'x-component': 'Action.Modal.Footer',
|
||||
properties: {
|
||||
close: {
|
||||
title: 'Close',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'default',
|
||||
useAction: useCancelAction,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
title: t('Scan QR code', { ns: 'block-workbench' }),
|
||||
},
|
||||
},
|
||||
} as ISchema);
|
||||
|
@ -0,0 +1,29 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export function ScanBox({ style = {} }: { style: React.CSSProperties }) {
|
||||
const commonStyle: React.CSSProperties = {
|
||||
position: 'absolute',
|
||||
backgroundColor: 'rgb(255, 255, 255)',
|
||||
};
|
||||
return (
|
||||
<div id="qr-scan-box" style={{ boxSizing: 'border-box', inset: '0px', ...style }}>
|
||||
<div style={{ width: '40px', height: '5px', top: '-5px', left: '0px', ...commonStyle }}></div>
|
||||
<div style={{ width: '40px', height: '5px', top: '-5px', right: '0px', ...commonStyle }}></div>
|
||||
<div style={{ width: '40px', height: '5px', bottom: '-5px', left: '0px', ...commonStyle }}></div>
|
||||
<div style={{ width: '40px', height: '5px', bottom: '-5px', right: '0px', ...commonStyle }}></div>
|
||||
<div style={{ width: '5px', height: '45px', top: '-5px', left: '-5px', ...commonStyle }}></div>
|
||||
<div style={{ width: '5px', height: '45px', bottom: '-5px', left: '-5px', ...commonStyle }}></div>
|
||||
<div style={{ width: '5px', height: '45px', top: '-5px', right: '-5px', ...commonStyle }}></div>
|
||||
<div style={{ width: '5px', height: '45px', bottom: '-5px', right: '-5px', ...commonStyle }}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -6,51 +6,177 @@
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
import { LeftOutlined, FileImageOutlined } from '@ant-design/icons';
|
||||
import { Html5Qrcode } from 'html5-qrcode';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useActionContext } from '@nocobase/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ScanBox } from './ScanBox';
|
||||
import { useScanner } from './useScanner';
|
||||
|
||||
import { Html5QrcodeScanner } from 'html5-qrcode';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import React, { useEffect } from 'react';
|
||||
const qrcodeEleId = 'qrcode';
|
||||
export const QRCodeScannerInner = (props) => {
|
||||
const containerRef = useRef<HTMLDivElement>();
|
||||
const imgUploaderRef = useRef<HTMLInputElement>();
|
||||
const { t } = useTranslation('block-workbench');
|
||||
const [originVideoSize, setOriginVideoSize] = useState({ width: 0, height: 0 });
|
||||
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
||||
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
||||
|
||||
const qrcodeRegionId = 'html5qr-code-full-region';
|
||||
const { startScanFile } = useScanner({
|
||||
onScannerSizeChanged: setOriginVideoSize,
|
||||
elementId: qrcodeEleId,
|
||||
});
|
||||
|
||||
// Creates the configuration object for Html5QrcodeScanner.
|
||||
const createConfig = (props) => {
|
||||
const config: any = {};
|
||||
if (props.fps) {
|
||||
config.fps = props.fps;
|
||||
const getBoxStyle = (): React.CSSProperties => {
|
||||
const size = Math.floor(Math.min(vw, vh) * 0.6);
|
||||
return {
|
||||
left: `${(vw - size) / 2}px`,
|
||||
top: `${(vh - size) / 2}px`,
|
||||
position: 'fixed',
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
};
|
||||
};
|
||||
|
||||
const onImgBtnClick = () => {
|
||||
if (imgUploaderRef.current) imgUploaderRef.current.click();
|
||||
};
|
||||
const onImgUploaded = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = event.target.files;
|
||||
if (files.length > 0) {
|
||||
const file = files[0];
|
||||
if (file.size < 1000000) startScanFile(file);
|
||||
else alert(t('The image size is too large. Please compress it to below 1MB before uploading'));
|
||||
}
|
||||
if (props.qrbox) {
|
||||
config.qrbox = props.qrbox;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.style.overscrollBehavior = 'none';
|
||||
return () => {
|
||||
document.documentElement.style.overscrollBehavior = 'default';
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { width, height } = originVideoSize;
|
||||
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
||||
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
||||
if (width > 0 && height > 0 && height < vh) {
|
||||
const zoomRatio = vh / height;
|
||||
const zoomedWidth = Math.floor(zoomRatio * width);
|
||||
const video = document.getElementsByTagName('video')[0];
|
||||
video.style.height = `${vh}px`;
|
||||
video.style.width = `${zoomedWidth}px`;
|
||||
containerRef.current.style.left = `${(vw - zoomedWidth) / 2}px`;
|
||||
containerRef.current.style.position = `absolute`;
|
||||
}
|
||||
if (props.aspectRatio) {
|
||||
config.aspectRatio = props.aspectRatio;
|
||||
}
|
||||
if (props.disableFlip !== undefined) {
|
||||
config.disableFlip = props.disableFlip;
|
||||
}
|
||||
return config;
|
||||
}, [originVideoSize]);
|
||||
|
||||
const ToolBar = () => {
|
||||
return (
|
||||
<div style={{ position: 'absolute', bottom: '20px', left: '20px', padding: '10px 60px' }}>
|
||||
<div
|
||||
style={{
|
||||
color: 'white',
|
||||
width: '40px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<FileImageOutlined style={imageBtnStyle} onClick={onImgBtnClick} />
|
||||
{t('Album')}
|
||||
<input
|
||||
ref={imgUploaderRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
onChange={onImgUploaded}
|
||||
style={{ visibility: 'hidden' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const imageBtnStyle: React.CSSProperties = {
|
||||
zIndex: '1003',
|
||||
fontSize: '1.8em',
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div ref={containerRef} id={qrcodeEleId} style={{ position: 'absolute' }} />
|
||||
<ScanBox style={{ ...getBoxStyle() }} />
|
||||
<ToolBar />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const QRCodeScanner = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const { visible, setVisible } = useActionContext();
|
||||
const [cameraAvaliable, setCameraAvaliable] = useState(false);
|
||||
const { t } = useTranslation('block-workbench');
|
||||
|
||||
useEffect(() => {
|
||||
// when component mounts
|
||||
const config = createConfig(props);
|
||||
const verbose = props.verbose === true;
|
||||
// Suceess callback is required.
|
||||
const qrCodeSuccessCallback = (decodedText, decodedResult) => {
|
||||
navigate(decodedText);
|
||||
const getCameras = async () => {
|
||||
try {
|
||||
const res = await Html5Qrcode.getCameras();
|
||||
if (res.length === 0) alert(t('No camera device detected'));
|
||||
else setCameraAvaliable(true);
|
||||
} catch (error) {
|
||||
const errMsgMap = {
|
||||
NotFoundError: t('No camera device detected'),
|
||||
NotAllowedError: t('You have not granted permission to use the camera'),
|
||||
};
|
||||
const html5QrcodeScanner = new Html5QrcodeScanner(qrcodeRegionId, config, verbose);
|
||||
html5QrcodeScanner.render(qrCodeSuccessCallback, props.qrCodeErrorCallback);
|
||||
console.log(error);
|
||||
const msg = errMsgMap[error.name];
|
||||
alert(msg ?? error);
|
||||
setCameraAvaliable(false);
|
||||
setVisible(false);
|
||||
}
|
||||
};
|
||||
if (visible && !cameraAvaliable) getCameras();
|
||||
}, [visible, cameraAvaliable, setVisible, t]);
|
||||
|
||||
// cleanup function when component will unmount
|
||||
return () => {
|
||||
html5QrcodeScanner.clear().catch((error) => {
|
||||
console.error('Failed to clear html5QrcodeScanner. ', error);
|
||||
});
|
||||
const style: React.CSSProperties = {
|
||||
position: 'fixed',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
background: 'black',
|
||||
zIndex: '1001',
|
||||
top: 0,
|
||||
left: 0,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
const backIconStyle: React.CSSProperties = {
|
||||
position: 'absolute',
|
||||
top: '22px',
|
||||
left: '20px',
|
||||
zIndex: '1003',
|
||||
color: 'white',
|
||||
fontSize: '1.8em',
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
}, [navigate, props]);
|
||||
|
||||
return <div id={qrcodeRegionId} />;
|
||||
const titleStyle: React.CSSProperties = {
|
||||
position: 'absolute',
|
||||
color: 'white',
|
||||
fontSize: '1.5em',
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: '20px',
|
||||
zIndex: '1002',
|
||||
marginLeft: 'auto',
|
||||
marginRight: 'auto',
|
||||
textAlign: 'center',
|
||||
};
|
||||
|
||||
return visible && cameraAvaliable ? (
|
||||
<div style={style}>
|
||||
<QRCodeScannerInner />
|
||||
<LeftOutlined style={backIconStyle} onClick={() => setVisible(false)} />
|
||||
<div style={titleStyle}>{t('Scan QR code')}</div>
|
||||
</div>
|
||||
) : null;
|
||||
};
|
||||
|
@ -0,0 +1,77 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { Html5Qrcode, Html5QrcodeScannerState } from 'html5-qrcode';
|
||||
import { useState, useCallback, useMemo, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export function useScanner({ onScannerSizeChanged, elementId }) {
|
||||
const [scanner, setScanner] = useState<Html5Qrcode>();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation('block-workbench');
|
||||
const viewPoint = useMemo(() => {
|
||||
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
|
||||
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
|
||||
return { width: vw, height: vh };
|
||||
}, []);
|
||||
|
||||
const startScanCamera = useCallback(
|
||||
async (scanner: Html5Qrcode) => {
|
||||
return scanner.start(
|
||||
{
|
||||
facingMode: 'environment',
|
||||
},
|
||||
{
|
||||
fps: 10,
|
||||
qrbox(width, height) {
|
||||
const minEdge = Math.min(width, height);
|
||||
onScannerSizeChanged({ width, height });
|
||||
return { width: viewPoint.width, height: viewPoint.height };
|
||||
},
|
||||
},
|
||||
(text) => {
|
||||
navigate(text);
|
||||
},
|
||||
undefined,
|
||||
);
|
||||
},
|
||||
[navigate, onScannerSizeChanged, viewPoint],
|
||||
);
|
||||
const stopScanner = useCallback(async (scanner: Html5Qrcode) => {
|
||||
const state = scanner.getState();
|
||||
if ([Html5QrcodeScannerState.SCANNING, Html5QrcodeScannerState.PAUSED].includes(state)) {
|
||||
return scanner.stop();
|
||||
} else return;
|
||||
}, []);
|
||||
|
||||
const startScanFile = useCallback(
|
||||
async (file: File) => {
|
||||
await stopScanner(scanner);
|
||||
try {
|
||||
const { decodedText } = await scanner.scanFileV2(file, false);
|
||||
navigate(decodedText);
|
||||
} catch (error) {
|
||||
alert(t('QR code recognition failed, please scan again'));
|
||||
startScanCamera(scanner);
|
||||
}
|
||||
},
|
||||
[scanner, stopScanner, startScanCamera, t, navigate],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const scanner = new Html5Qrcode(elementId);
|
||||
setScanner(scanner);
|
||||
startScanCamera(scanner);
|
||||
return () => {
|
||||
stopScanner(scanner);
|
||||
};
|
||||
}, [elementId, startScanCamera, stopScanner]);
|
||||
return { startScanCamera, startScanFile };
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
{
|
||||
"Workbench": "工作台",
|
||||
"Scan QR code": "扫描二维码"
|
||||
"Scan QR code": "扫描二维码",
|
||||
"Album": "相册",
|
||||
"No camera device detected": "未检测到摄像头设备",
|
||||
"You have not granted permission to use the camera": "您未授权使用摄像头",
|
||||
"Unknown error": "未知错误",
|
||||
"The image size is too large. Please compress it to below 1MB before uploading": "图片尺寸过大,请压缩到1MB以下上传",
|
||||
"QR code recognition failed, please scan again": "二维码识别失败,请重新扫描"
|
||||
}
|
111
yarn.lock
111
yarn.lock
@ -217,6 +217,11 @@
|
||||
resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.3.1.tgz#4b2f65a17d4d32b526baa6414aca2117382bf8da"
|
||||
integrity sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==
|
||||
|
||||
"@ant-design/icons-svg@^4.4.0":
|
||||
version "4.4.2"
|
||||
resolved "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6"
|
||||
integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==
|
||||
|
||||
"@ant-design/icons@5.x", "@ant-design/icons@^5.0.0", "@ant-design/icons@^5.1.3", "@ant-design/icons@^5.1.4", "@ant-design/icons@^5.2.5", "@ant-design/icons@^5.2.6":
|
||||
version "5.2.6"
|
||||
resolved "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.2.6.tgz#2d4a9a37f531eb2a20cebec01d6fb69cf593900d"
|
||||
@ -228,6 +233,17 @@
|
||||
classnames "^2.2.6"
|
||||
rc-util "^5.31.1"
|
||||
|
||||
"@ant-design/icons@^5.3.7":
|
||||
version "5.3.7"
|
||||
resolved "https://registry.npmmirror.com/@ant-design/icons/-/icons-5.3.7.tgz#d9f3654bf7934ee5faba43f91b5a187f5309ec68"
|
||||
integrity sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew==
|
||||
dependencies:
|
||||
"@ant-design/colors" "^7.0.0"
|
||||
"@ant-design/icons-svg" "^4.4.0"
|
||||
"@babel/runtime" "^7.11.2"
|
||||
classnames "^2.2.6"
|
||||
rc-util "^5.31.1"
|
||||
|
||||
"@ant-design/plots@^2.1.4":
|
||||
version "2.1.14"
|
||||
resolved "https://registry.npmmirror.com/@ant-design/plots/-/plots-2.1.14.tgz#967a6fbf3e86ad216026fdbb853af1391549c795"
|
||||
@ -5172,11 +5188,6 @@
|
||||
resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.14.0.tgz#9bc39a5a3a71b81bdb310eba6def5bc3966695b7"
|
||||
integrity sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A==
|
||||
|
||||
"@remix-run/router@1.16.1":
|
||||
version "1.16.1"
|
||||
resolved "https://registry.npmmirror.com/@remix-run/router/-/router-1.16.1.tgz#73db3c48b975eeb06d0006481bde4f5f2d17d1cd"
|
||||
integrity sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==
|
||||
|
||||
"@restart/hooks@^0.4.7":
|
||||
version "0.4.15"
|
||||
resolved "https://registry.npmmirror.com/@restart/hooks/-/hooks-0.4.15.tgz#70990085c9b79d1f3e140db824b29218bdc2b5bb"
|
||||
@ -6788,13 +6799,20 @@
|
||||
"@types/prop-types" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@17.x", "@types/react-dom@^17.0.0", "@types/react-dom@^18.0.0":
|
||||
"@types/react-dom@17.x", "@types/react-dom@^17.0.0":
|
||||
version "17.0.25"
|
||||
resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-17.0.25.tgz#e0e5b3571e1069625b3a3da2b279379aa33a0cb5"
|
||||
integrity sha512-urx7A7UxkZQmThYA4So0NelOVjx3V4rNFVJwp0WZlbIK5eM4rNJDiN3R/E9ix0MBh6kAEojk/9YL+Te6D9zHNA==
|
||||
dependencies:
|
||||
"@types/react" "^17"
|
||||
|
||||
"@types/react-dom@^18.0.0":
|
||||
version "18.3.0"
|
||||
resolved "https://registry.npmmirror.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
|
||||
integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-redux@^7.1.20":
|
||||
version "7.1.33"
|
||||
resolved "https://registry.npmmirror.com/@types/react-redux/-/react-redux-7.1.33.tgz#53c5564f03f1ded90904e3c90f77e4bd4dc20b15"
|
||||
@ -6805,7 +6823,7 @@
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
redux "^4.0.0"
|
||||
|
||||
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@17.x", "@types/react@>=16.9.11", "@types/react@^17", "@types/react@^17.0.0", "@types/react@^18.0.0":
|
||||
"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@17.x", "@types/react@>=16.9.11", "@types/react@^17", "@types/react@^17.0.0":
|
||||
version "17.0.73"
|
||||
resolved "https://registry.npmmirror.com/@types/react/-/react-17.0.73.tgz#23a663c803b18d8b7f4f2bb9b467f2f3fd70787a"
|
||||
integrity sha512-6AcjgPIVsXTIsFDgsGW0iQhvg0xb2vt2qAWgXyncnVNRaW9ZXTTwAh7RQoh7PzK1AhjPoGDvUBkdAREih9n5oQ==
|
||||
@ -6814,6 +6832,14 @@
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/react@^18.0.0":
|
||||
version "18.3.3"
|
||||
resolved "https://registry.npmmirror.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f"
|
||||
integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/readdir-glob@*":
|
||||
version "1.1.5"
|
||||
resolved "https://registry.npmmirror.com/@types/readdir-glob/-/readdir-glob-1.1.5.tgz#21a4a98898fc606cb568ad815f2a0eedc24d412a"
|
||||
@ -7046,7 +7072,17 @@
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/parser@^5.62.0", "@typescript-eslint/parser@^6.2.0":
|
||||
"@typescript-eslint/parser@^5.62.0":
|
||||
version "5.62.0"
|
||||
resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.62.0.tgz#1b63d082d849a2fcae8a569248fbe2ee1b8a56c7"
|
||||
integrity sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.62.0"
|
||||
"@typescript-eslint/types" "5.62.0"
|
||||
"@typescript-eslint/typescript-estree" "5.62.0"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/parser@^6.2.0":
|
||||
version "6.21.0"
|
||||
resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b"
|
||||
integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
|
||||
@ -8125,7 +8161,7 @@ antd-token-previewer@^2.0.0-alpha.6:
|
||||
use-debouncy "~4.3.0"
|
||||
vanilla-jsoneditor "^0.16.1"
|
||||
|
||||
antd@5.12.8, antd@5.x, antd@^5.12.8, antd@^5.5.1:
|
||||
antd@5.x, antd@^5.12.8, antd@^5.5.1, antd@^5.x:
|
||||
version "5.12.8"
|
||||
resolved "https://registry.npmmirror.com/antd/-/antd-5.12.8.tgz#94fea825e9bae535af7adf70417fa1f0dadc4c98"
|
||||
integrity sha512-R2CRcB+aaVZurb3J0IKpBRWq5kW4CLcSqDF58/QBsqYdzK7XjSvM8+eF3rWVRUDbSJfGmyW7I80ywNRYpW1+vA==
|
||||
@ -14908,7 +14944,7 @@ highlight.js@^10.1.0, highlight.js@^10.2.0:
|
||||
resolved "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
|
||||
|
||||
history@5.3.0:
|
||||
history@5.3.0, history@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmmirror.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b"
|
||||
integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==
|
||||
@ -19337,7 +19373,7 @@ number-is-nan@^1.0.0:
|
||||
resolved "https://registry.npmmirror.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==
|
||||
|
||||
nwsapi@2.2.7, nwsapi@^2.2.0:
|
||||
nwsapi@^2.2.0:
|
||||
version "2.2.7"
|
||||
resolved "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30"
|
||||
integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
|
||||
@ -21871,7 +21907,15 @@ react-copy-to-clipboard@^5.1.0:
|
||||
copy-to-clipboard "^3.3.1"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
react-dom@18.1.0, react-dom@18.x, react-dom@^18.0.0, react-dom@^18.2.0:
|
||||
react-dom@18.1.0:
|
||||
version "18.1.0"
|
||||
resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.1.0.tgz#7f6dd84b706408adde05e1df575b3a024d7e8a2f"
|
||||
integrity sha512-fU1Txz7Budmvamp7bshe4Zi32d0ll7ect+ccxNu9FlObT605GOEB8BfO4tmRJ39R5Zj831VCpvQ05QPBW5yb+w==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.22.0"
|
||||
|
||||
react-dom@18.x, react-dom@^18.0.0, react-dom@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmmirror.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
|
||||
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
|
||||
@ -22063,7 +22107,15 @@ react-refresh@0.14.0, react-refresh@^0.14.0:
|
||||
resolved "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.14.0.tgz#4e02825378a5f227079554d4284889354e5f553e"
|
||||
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
|
||||
|
||||
react-router-dom@6.3.0, react-router-dom@6.x, react-router-dom@^6.11.2, react-router-dom@^6.x:
|
||||
react-router-dom@6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d"
|
||||
integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==
|
||||
dependencies:
|
||||
history "^5.2.0"
|
||||
react-router "6.3.0"
|
||||
|
||||
react-router-dom@6.x, react-router-dom@^6.11.2, react-router-dom@^6.x:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.21.0.tgz#aa4c6bc046a8e8723095bc09b3c0ab2254532712"
|
||||
integrity sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ==
|
||||
@ -22071,12 +22123,19 @@ react-router-dom@6.3.0, react-router-dom@6.x, react-router-dom@^6.11.2, react-ro
|
||||
"@remix-run/router" "1.14.0"
|
||||
react-router "6.21.0"
|
||||
|
||||
react-router@6.21.0, react-router@6.3.0, react-router@^6.11.2:
|
||||
version "6.23.1"
|
||||
resolved "https://registry.npmmirror.com/react-router/-/react-router-6.23.1.tgz#d08cbdbd9d6aedc13eea6e94bc6d9b29cb1c4be9"
|
||||
integrity sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==
|
||||
react-router@6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://registry.npmmirror.com/react-router/-/react-router-6.21.0.tgz#6fe3e59877aca3dccceec1801d26991ddf42d12b"
|
||||
integrity sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.16.1"
|
||||
"@remix-run/router" "1.14.0"
|
||||
|
||||
react-router@6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.npmmirror.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557"
|
||||
integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==
|
||||
dependencies:
|
||||
history "^5.2.0"
|
||||
|
||||
react-side-effect@^2.1.0:
|
||||
version "2.1.2"
|
||||
@ -22095,7 +22154,14 @@ react-to-print@^2.14.7:
|
||||
resolved "https://registry.npmmirror.com/react-to-print/-/react-to-print-2.14.15.tgz#edb4ce8a92205cf37fd8c3d57de829034aa5c911"
|
||||
integrity sha512-SKnwOzU2cJ8eaAkoJO7+gNhvfEDmm+Y34IdcHsjtHioUevUPhprqbVtvNJlZ2JkGJ8ExK2QNWM9pXECTDR5D8w==
|
||||
|
||||
react@18.1.0, react@18.x, react@^18.0.0, react@^18.2.0:
|
||||
react@18.1.0:
|
||||
version "18.1.0"
|
||||
resolved "https://registry.npmmirror.com/react/-/react-18.1.0.tgz#6f8620382decb17fdc5cc223a115e2adbf104890"
|
||||
integrity sha512-4oL8ivCz5ZEPyclFQXaNksK3adutVS8l2xzZU0cqEFrE9Sb7fC0EFK5uEk74wIreL1DERyjvsU915j1pcT2uEQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
react@18.x, react@^18.0.0, react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmmirror.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||
@ -23095,6 +23161,13 @@ saxes@^5.0.1:
|
||||
dependencies:
|
||||
xmlchars "^2.2.0"
|
||||
|
||||
scheduler@^0.22.0:
|
||||
version "0.22.0"
|
||||
resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.22.0.tgz#83a5d63594edf074add9a7198b1bae76c3db01b8"
|
||||
integrity sha512-6QAm1BgQI88NPYymgGQLCZgvep4FyePDWFpXVK+zNSUgHwlqpJy8VEh8Et0KxTACS4VWwMousBElAZOH9nkkoQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
scheduler@^0.23.0:
|
||||
version "0.23.0"
|
||||
resolved "https://registry.npmmirror.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
|
||||
|
Loading…
Reference in New Issue
Block a user