diff --git a/README.md b/README.md index adc5686..91ba0f6 100644 --- a/README.md +++ b/README.md @@ -504,6 +504,56 @@ render(); ``` +- JsonPreview +- JSON文件预览 +- _ReactFile(@kne/current-lib_react-file)[import * as _ReactFile from "@kne/react-file"],(@kne/current-lib_react-file/dist/index.css),remoteLoader(@kne/remote-loader) + +```jsx +const { JsonPreview } = _ReactFile; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +const BaseExample = createWithRemoteLoader({ + modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage'] +})(({ remoteModules }) => { + const [PureGlobal, InfoPage] = remoteModules; + return ( + { + return { data: { code: 0, data: api.loader() } }; + }, + apis: { + file: { + staticUrl: getPublicPath('react-file') || window.PUBLIC_URL + } + } + }}> + + + + + + + + + + + + + ); +}); + +render(); + +``` + ### API @@ -562,6 +612,33 @@ ZIP压缩包文件预览组件,支持查看压缩包内部的文件列表和 - `.tar` - TAR归档文件 - `.gz` - Gzip压缩文件 +### JsonPreview + +JSON文件预览组件,使用 @kne/json-view 提供友好的 JSON 数据展示。 + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|------|------|--------|------| +| url | string | - | JSON文件的URL地址 | +| className | string | - | 自定义容器类名 | +| maxWidth | string/number | - | 容器最大宽度 | +| theme | 'light' \| 'dark' | 'dark' | 主题模式 | +| collapsedFrom | number | - | 从第几级开始收起,默认全部展开 | +| searchable | boolean | true | 是否开启搜索功能 | +| collapsable | boolean | true | 是否显示展开/收起全部按钮 | +| indentWidth | number | 20 | 缩进宽度(像素) | +| showLineNumbers | boolean | true | 是否显示行号 | + +#### 功能特性 + +- 语法高亮:不同数据类型使用不同颜色 +- 层级控制:支持展开/收起,可指定从第几级开始收起 +- 搜索功能:基于 Fuse.js 的模糊搜索,关键字高亮 +- 双主题支持:白色和黑色两种主题 +- 复制功能:一键复制格式化的 JSON 数据 +- 行号显示:左侧显示行号 + ### FilePreview 文件预览组件,支持多种文件格式的预览。 diff --git a/doc/api.md b/doc/api.md index 68b4bf4..5b78938 100644 --- a/doc/api.md +++ b/doc/api.md @@ -53,6 +53,33 @@ ZIP压缩包文件预览组件,支持查看压缩包内部的文件列表和 - `.tar` - TAR归档文件 - `.gz` - Gzip压缩文件 +### JsonPreview + +JSON文件预览组件,使用 @kne/json-view 提供友好的 JSON 数据展示。 + +#### 属性 + +| 属性 | 类型 | 默认值 | 描述 | +|------|------|--------|------| +| url | string | - | JSON文件的URL地址 | +| className | string | - | 自定义容器类名 | +| maxWidth | string/number | - | 容器最大宽度 | +| theme | 'light' \| 'dark' | 'dark' | 主题模式 | +| collapsedFrom | number | - | 从第几级开始收起,默认全部展开 | +| searchable | boolean | true | 是否开启搜索功能 | +| collapsable | boolean | true | 是否显示展开/收起全部按钮 | +| indentWidth | number | 20 | 缩进宽度(像素) | +| showLineNumbers | boolean | true | 是否显示行号 | + +#### 功能特性 + +- 语法高亮:不同数据类型使用不同颜色 +- 层级控制:支持展开/收起,可指定从第几级开始收起 +- 搜索功能:基于 Fuse.js 的模糊搜索,关键字高亮 +- 双主题支持:白色和黑色两种主题 +- 复制功能:一键复制格式化的 JSON 数据 +- 行号显示:左侧显示行号 + ### FilePreview 文件预览组件,支持多种文件格式的预览。 diff --git a/doc/example.json b/doc/example.json index 6d7351e..89a1d0a 100644 --- a/doc/example.json +++ b/doc/example.json @@ -176,6 +176,25 @@ "packageName": "@kne/remote-loader" } ] + }, + { + "title": "JsonPreview", + "description": "JSON文件预览", + "code": "./json-preview.js", + "scope": [ + { + "name": "_ReactFile", + "packageName": "@kne/current-lib_react-file", + "importStatement": "import * as _ReactFile from \"@kne/react-file\"" + }, + { + "packageName": "@kne/current-lib_react-file/dist/index.css" + }, + { + "name": "remoteLoader", + "packageName": "@kne/remote-loader" + } + ] } ] } diff --git a/doc/json-preview.js b/doc/json-preview.js new file mode 100644 index 0000000..1f2647c --- /dev/null +++ b/doc/json-preview.js @@ -0,0 +1,42 @@ +const { JsonPreview } = _ReactFile; +const { createWithRemoteLoader, getPublicPath } = remoteLoader; + +const BaseExample = createWithRemoteLoader({ + modules: ['components-core:Global@PureGlobal', 'components-core:InfoPage'] +})(({ remoteModules }) => { + const [PureGlobal, InfoPage] = remoteModules; + return ( + { + return { data: { code: 0, data: api.loader() } }; + }, + apis: { + file: { + staticUrl: getPublicPath('react-file') || window.PUBLIC_URL + } + } + }}> + + + + + + + + + + + + + ); +}); + +render(); diff --git a/package.json b/package.json index 2c5e3b1..ca185e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kne/react-file", - "version": "0.1.35", + "version": "0.1.36", "description": "提供了文件上传,文件预览,文件批量管理等功能", "syntax": { "esmodules": true @@ -92,6 +92,7 @@ "@kne/create-deferred": "^0.1.0", "@kne/global-context": "^1.3.2", "@kne/iframe-resizer": "^0.1.3", + "@kne/json-view": "^0.1.1", "@kne/markdown-components-render": "^0.1.10", "@kne/react-fetch": "^1.5.5", "@kne/react-file-type": "^1.0.9", diff --git a/src/components/FilePreview/JsonPreview.js b/src/components/FilePreview/JsonPreview.js new file mode 100644 index 0000000..36f1e11 --- /dev/null +++ b/src/components/FilePreview/JsonPreview.js @@ -0,0 +1,66 @@ +import React, { useState, useEffect } from 'react'; +import { getAjax } from '@kne/react-fetch'; +import JsonView from '@kne/json-view'; +import style from './style.module.scss'; +import { Spin } from 'antd'; +import classnames from 'classnames'; +import { createWithIntlProvider, useIntl } from '@kne/react-intl'; +import zhCn from '../../locale/zh-CN'; +import '@kne/json-view/dist/index.css'; + +const JsonPreview = createWithIntlProvider( + 'zh-CN', + zhCn, + 'react-file' +)(({ url, className, maxWidth, theme = 'dark', collapsedFrom, searchable = true, collapsable = true, indentWidth = 20, showLineNumbers = true }) => { + const { formatMessage } = useIntl(); + const [data, setData] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + + useEffect(() => { + const ajax = getAjax(); + ajax({ url, method: 'GET' }).then( + ({ data: responseData }) => { + try { + // 如果返回的是字符串,尝试解析为 JSON + const jsonData = typeof responseData === 'string' ? JSON.parse(responseData) : responseData; + setData(jsonData); + setLoading(false); + } catch (e) { + console.error('JSON parse error:', e); + setError(true); + setLoading(false); + } + }, + () => { + setLoading(false); + setError(true); + } + ); + }, [url]); + + return ( +
+ {loading ? ( +
+ +
+ ) : null} +
+ {error ? ( +
{formatMessage({ id: 'fileLoadedError' })}
+ ) : ( + + )} +
+
+ ); +}); + +export default JsonPreview; diff --git a/src/components/FilePreview/index.js b/src/components/FilePreview/index.js index 2edd525..697138d 100644 --- a/src/components/FilePreview/index.js +++ b/src/components/FilePreview/index.js @@ -10,4 +10,5 @@ export { default as AudioPreview } from './AudioPreview'; export { default as VideoPreview } from './VideoPreview'; export { default as MarkdownPreview } from './MarkdownPreview'; export { default as ZipPreview } from './ZipPreview'; +export { default as JsonPreview } from './JsonPreview'; export { default as typeFormat, typeComponentMapping } from './typeFormat'; diff --git a/src/components/FilePreview/typeFormat.js b/src/components/FilePreview/typeFormat.js index b6fa16b..dee4180 100644 --- a/src/components/FilePreview/typeFormat.js +++ b/src/components/FilePreview/typeFormat.js @@ -8,6 +8,7 @@ import AudioPreview from './AudioPreview'; import VideoPreview from './VideoPreview'; import MarkdownPreview from './MarkdownPreview'; import ZipPreview from './ZipPreview'; +import JsonPreview from './JsonPreview'; const typeFormat = url => { if (typeof url !== 'string') { @@ -24,7 +25,7 @@ const typeFormat = url => { if (/.pdf$/.test(_path)) { return 'pdf'; } - if (/.(png|jpg|jpeg)$/.test(_path)) { + if (/.(png|jpg|jpeg|gif|bmp|webp|svg)$/.test(_path)) { return 'image'; } if (/.(html|htm)$/.test(_path)) { @@ -42,6 +43,9 @@ const typeFormat = url => { if (/.(zip|rar|7z|tar|gz)$/.test(_path)) { return 'zip'; } + if (/.json$/.test(_path)) { + return 'json'; + } return 'unknown'; }; @@ -57,6 +61,7 @@ export const typeComponentMapping = { audio: AudioPreview, video: VideoPreview, zip: ZipPreview, + json: JsonPreview, unknown: UnknownPreview }; diff --git a/src/index.js b/src/index.js index ae0ba88..977e9e8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ export { default } from './components/File'; export { default as Download, useDownload, download, downloadBlobFile } from './components/Download'; -export { default as FilePreview, ZipPreview, HtmlPreview, PdfPreview, TextPreview, MarkdownPreview, ImagePreview, UnknownPreview, OfficePreview, OSSFilePreview, AudioPreview, VideoPreview } from './components/FilePreview'; +export { default as FilePreview, ZipPreview, JsonPreview, HtmlPreview, PdfPreview, TextPreview, MarkdownPreview, ImagePreview, UnknownPreview, OfficePreview, OSSFilePreview, AudioPreview, VideoPreview } from './components/FilePreview'; export { default as FileButton, useFileModalProps, useFileModal, FileModal } from './components/FileButton'; export { default as Image } from './components/Image'; export { default as PrintButton } from './components/PrintButton';