@kne-components/components-core 0.4.66 → 0.4.67
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/build/asset-manifest.json +91 -91
- package/build/index.html +1 -1
- package/build/remoteEntry.js +1 -1
- package/build/remoteEntry.js.map +1 -1
- package/build/static/css/111.f68f5313.chunk.css +2 -0
- package/build/static/css/{111.af43bf41.chunk.css.map → 111.f68f5313.chunk.css.map} +1 -1
- package/build/static/css/2753.e7949ab3.chunk.css +2 -0
- package/build/static/css/{2753.65190152.chunk.css.map → 2753.e7949ab3.chunk.css.map} +1 -1
- package/build/static/css/{3771.a16d89be.chunk.css → 3771.ff018f27.chunk.css} +2 -2
- package/build/static/css/{3771.a16d89be.chunk.css.map → 3771.ff018f27.chunk.css.map} +1 -1
- package/build/static/css/{3790.5abb16a3.chunk.css → 3790.4526e53c.chunk.css} +2 -2
- package/build/static/css/{3790.5abb16a3.chunk.css.map → 3790.4526e53c.chunk.css.map} +1 -1
- package/build/static/css/3841.c7026264.chunk.css +2 -0
- package/build/static/css/{3841.9195867c.chunk.css.map → 3841.c7026264.chunk.css.map} +1 -1
- package/build/static/css/3874.5d044f62.chunk.css +2 -0
- package/build/static/css/{3874.4a2de703.chunk.css.map → 3874.5d044f62.chunk.css.map} +1 -1
- package/build/static/css/{4302.dad10603.chunk.css → 4302.651d68fa.chunk.css} +2 -2
- package/build/static/css/{4302.dad10603.chunk.css.map → 4302.651d68fa.chunk.css.map} +1 -1
- package/build/static/css/4666.8f03839e.chunk.css +2 -0
- package/build/static/css/{4666.2c927cd4.chunk.css.map → 4666.8f03839e.chunk.css.map} +1 -1
- package/build/static/css/5628.e4fcb2cc.chunk.css +12 -0
- package/build/static/css/{5628.97e556c6.chunk.css.map → 5628.e4fcb2cc.chunk.css.map} +1 -1
- package/build/static/css/{6763.3f4c0ba1.chunk.css → 6763.a832c4fd.chunk.css} +2 -2
- package/build/static/css/{6763.3f4c0ba1.chunk.css.map → 6763.a832c4fd.chunk.css.map} +1 -1
- package/build/static/css/7227.031856f2.chunk.css +2 -0
- package/build/static/css/{7227.2a0a9dd0.chunk.css.map → 7227.031856f2.chunk.css.map} +1 -1
- package/build/static/css/7372.5d6553e3.chunk.css +2 -0
- package/build/static/css/{7372.e23f18b8.chunk.css.map → 7372.5d6553e3.chunk.css.map} +1 -1
- package/build/static/css/{760.7bd56434.chunk.css → 760.27c95225.chunk.css} +2 -2
- package/build/static/css/{760.7bd56434.chunk.css.map → 760.27c95225.chunk.css.map} +1 -1
- package/build/static/css/{8221.99a45fda.chunk.css → 8221.bcf604af.chunk.css} +2 -2
- package/build/static/css/{8221.99a45fda.chunk.css.map → 8221.bcf604af.chunk.css.map} +1 -1
- package/build/static/css/8377.1bbf012a.chunk.css +2 -0
- package/build/static/css/{8377.a8cb24d1.chunk.css.map → 8377.1bbf012a.chunk.css.map} +1 -1
- package/build/static/css/{8593.11db5d93.chunk.css → 8593.e59836d7.chunk.css} +2 -2
- package/build/static/css/{8593.11db5d93.chunk.css.map → 8593.e59836d7.chunk.css.map} +1 -1
- package/build/static/css/9387.59954fd1.chunk.css +2 -0
- package/build/static/css/{9387.d02253f6.chunk.css.map → 9387.59954fd1.chunk.css.map} +1 -1
- package/build/static/css/9556.27566499.chunk.css +2 -0
- package/build/static/css/{9556.828a556c.chunk.css.map → 9556.27566499.chunk.css.map} +1 -1
- package/build/static/css/9666.a4e2b163.chunk.css +2 -0
- package/build/static/css/{9666.d8c91149.chunk.css.map → 9666.a4e2b163.chunk.css.map} +1 -1
- package/build/static/js/{111.f812617f.chunk.js → 111.f4b5ea98.chunk.js} +2 -2
- package/build/static/js/{111.f812617f.chunk.js.map → 111.f4b5ea98.chunk.js.map} +1 -1
- package/build/static/js/{196.74a1326d.chunk.js → 196.80a3177c.chunk.js} +1 -1
- package/build/static/js/{2833.2cdd46e6.chunk.js → 2833.1d09d414.chunk.js} +2 -2
- package/build/static/js/2833.1d09d414.chunk.js.map +1 -0
- package/build/static/js/3771.0d3884d1.chunk.js +2 -0
- package/build/static/js/{3771.e50184d9.chunk.js.map → 3771.0d3884d1.chunk.js.map} +1 -1
- package/build/static/js/{3790.03afba35.chunk.js → 3790.595590c0.chunk.js} +2 -2
- package/build/static/js/{3790.03afba35.chunk.js.map → 3790.595590c0.chunk.js.map} +1 -1
- package/build/static/js/{3841.de64ea1f.chunk.js → 3841.bcb1e477.chunk.js} +2 -2
- package/build/static/js/{3841.de64ea1f.chunk.js.map → 3841.bcb1e477.chunk.js.map} +1 -1
- package/build/static/js/{3856.3bc4f554.chunk.js → 3856.9b306735.chunk.js} +2 -2
- package/build/static/js/{3856.3bc4f554.chunk.js.map → 3856.9b306735.chunk.js.map} +1 -1
- package/build/static/js/{3874.43b3a191.chunk.js → 3874.f239c12f.chunk.js} +3 -3
- package/build/static/js/{3874.43b3a191.chunk.js.map → 3874.f239c12f.chunk.js.map} +1 -1
- package/build/static/js/4302.1e65d1a3.chunk.js +2 -0
- package/build/static/js/{4302.77e57d61.chunk.js.map → 4302.1e65d1a3.chunk.js.map} +1 -1
- package/build/static/js/4474.25d1469a.chunk.js +2 -0
- package/build/static/js/{4474.19db5271.chunk.js.map → 4474.25d1469a.chunk.js.map} +1 -1
- package/build/static/js/{4666.ced49dea.chunk.js → 4666.da12dcad.chunk.js} +3 -3
- package/build/static/js/{4666.ced49dea.chunk.js.map → 4666.da12dcad.chunk.js.map} +1 -1
- package/build/static/js/{2363.e9d2eed8.chunk.js → 4744.68f457ed.chunk.js} +2 -2
- package/build/static/js/{2363.e9d2eed8.chunk.js.map → 4744.68f457ed.chunk.js.map} +1 -1
- package/build/static/js/5628.92cde7ac.chunk.js +2 -0
- package/build/static/js/{5628.72e29acc.chunk.js.map → 5628.92cde7ac.chunk.js.map} +1 -1
- package/build/static/js/6460.c05b642e.chunk.js +9 -0
- package/build/static/js/6460.c05b642e.chunk.js.map +1 -0
- package/build/static/js/6763.f212e86e.chunk.js +2 -0
- package/build/static/js/{6763.3a0a852f.chunk.js.map → 6763.f212e86e.chunk.js.map} +1 -1
- package/build/static/js/{7227.d189f8e3.chunk.js → 7227.9ba0d1ca.chunk.js} +3 -3
- package/build/static/js/{7227.d189f8e3.chunk.js.map → 7227.9ba0d1ca.chunk.js.map} +1 -1
- package/build/static/js/{7372.7e6e421a.chunk.js → 7372.2abd5112.chunk.js} +2 -2
- package/build/static/js/{7372.7e6e421a.chunk.js.map → 7372.2abd5112.chunk.js.map} +1 -1
- package/build/static/js/{760.185e0aa5.chunk.js → 760.64ddb4b7.chunk.js} +2 -2
- package/build/static/js/{760.185e0aa5.chunk.js.map → 760.64ddb4b7.chunk.js.map} +1 -1
- package/build/static/js/7857.07e102fc.chunk.js +2 -0
- package/build/static/js/{7857.6ed907e0.chunk.js.map → 7857.07e102fc.chunk.js.map} +1 -1
- package/build/static/js/8221.5cde284c.chunk.js +2 -0
- package/build/static/js/{8221.c93d129f.chunk.js.map → 8221.5cde284c.chunk.js.map} +1 -1
- package/build/static/js/{8377.f4903a9e.chunk.js → 8377.32461eb9.chunk.js} +2 -2
- package/build/static/js/{8377.f4903a9e.chunk.js.map → 8377.32461eb9.chunk.js.map} +1 -1
- package/build/static/js/8593.53fd497a.chunk.js +2 -0
- package/build/static/js/{8593.18b7475f.chunk.js.map → 8593.53fd497a.chunk.js.map} +1 -1
- package/build/static/js/{9223.800c4315.chunk.js → 9223.0adf8af5.chunk.js} +2 -2
- package/build/static/js/9223.0adf8af5.chunk.js.map +1 -0
- package/build/static/js/9556.59fe644a.chunk.js +3 -0
- package/build/static/js/{9556.2fa191f6.chunk.js.map → 9556.59fe644a.chunk.js.map} +1 -1
- package/build/static/js/9666.51562fa6.chunk.js +2 -0
- package/build/static/js/{9666.61a8e69f.chunk.js.map → 9666.51562fa6.chunk.js.map} +1 -1
- package/build/static/js/{main.94eeacc5.js → main.3892a3eb.js} +2 -2
- package/build/static/js/{main.94eeacc5.js.map → main.3892a3eb.js.map} +1 -1
- package/package.json +2 -2
- package/build/static/css/111.af43bf41.chunk.css +0 -2
- package/build/static/css/2753.65190152.chunk.css +0 -2
- package/build/static/css/3841.9195867c.chunk.css +0 -2
- package/build/static/css/3874.4a2de703.chunk.css +0 -2
- package/build/static/css/4666.2c927cd4.chunk.css +0 -2
- package/build/static/css/5628.97e556c6.chunk.css +0 -12
- package/build/static/css/7227.2a0a9dd0.chunk.css +0 -2
- package/build/static/css/7372.e23f18b8.chunk.css +0 -2
- package/build/static/css/8377.a8cb24d1.chunk.css +0 -2
- package/build/static/css/9387.d02253f6.chunk.css +0 -2
- package/build/static/css/9556.828a556c.chunk.css +0 -2
- package/build/static/css/9666.d8c91149.chunk.css +0 -2
- package/build/static/js/2833.2cdd46e6.chunk.js.map +0 -1
- package/build/static/js/3771.e50184d9.chunk.js +0 -2
- package/build/static/js/4302.77e57d61.chunk.js +0 -2
- package/build/static/js/4474.19db5271.chunk.js +0 -2
- package/build/static/js/5628.72e29acc.chunk.js +0 -2
- package/build/static/js/6460.02f933ea.chunk.js +0 -9
- package/build/static/js/6460.02f933ea.chunk.js.map +0 -1
- package/build/static/js/6763.3a0a852f.chunk.js +0 -2
- package/build/static/js/7857.6ed907e0.chunk.js +0 -2
- package/build/static/js/8221.c93d129f.chunk.js +0 -2
- package/build/static/js/8593.18b7475f.chunk.js +0 -2
- package/build/static/js/9223.800c4315.chunk.js.map +0 -1
- package/build/static/js/9556.2fa191f6.chunk.js +0 -3
- package/build/static/js/9666.61a8e69f.chunk.js +0 -2
- /package/build/static/js/{3874.43b3a191.chunk.js.LICENSE.txt → 3874.f239c12f.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{4666.ced49dea.chunk.js.LICENSE.txt → 4666.da12dcad.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{6460.02f933ea.chunk.js.LICENSE.txt → 6460.c05b642e.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{7227.d189f8e3.chunk.js.LICENSE.txt → 7227.9ba0d1ca.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{9556.2fa191f6.chunk.js.LICENSE.txt → 9556.59fe644a.chunk.js.LICENSE.txt} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static/js/2833.2cdd46e6.chunk.js","mappings":"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","sources":["components/ButtonGroup/README.md","components/Common/README.md","components/Drawer/README.md","components/Enum/README.md","components/Features/README.md","components/File/README.md","components/FileList/README.md","components/FilePreview/README.md","components/Filter/README.md","components/FlexBox/README.md","components/FormInfo/README.md","components/Global/README.md","components/HelperGuide/README.md","components/HistoryStore/README.md","components/Icon/README.md","components/Image/README.md","components/InfoPage/README.md","components/Layout/README.md","components/Menu/README.md","components/Modal/README.md","components/Navigation/README.md","components/Permissions/README.md","components/StateBar/README.md","components/StateTag/README.md","components/Table/README.md","components/Tooltip/README.md","webpack://@kne-components/components-core/./src/components/HistoryStore/style.module.scss?1856","components/HistoryStore/index.js"],"sourcesContent":["import * as component_36 from '@kne/button-group';\nimport * as component_37 from 'antd';\nimport '@kne/button-group/dist/index.css';\nimport '@kne/button-group/dist/index.css';\nconst readmeConfig = {\n name: `button-group`,\n summary: `<p>@kne/button-group 是一个 React 按钮组件库,提供了一系列功能丰富的按钮组件,用于简化常见的按钮交互场景。该库专注于提供自适应布局、加载状态管理、确认操作和数据请求等功能,使开发者能够快速实现各种复杂的按钮交互需求。</p>\n<h3>ButtonGroup</h3>\n<p>自适应按钮组组件,能够根据容器宽度自动调整显示的按钮数量。当容器宽度不足以显示所有按钮时,会自动将多余的按钮放入下拉菜单中,确保界面布局美观且功能完整。</p>\n<p><strong>主要特性:</strong></p>\n<ul>\n<li>自动适应容器宽度</li>\n<li>支持紧凑模式(Space.Compact)</li>\n<li>支持链接样式(适用于表格操作列)</li>\n<li>可指定显示的按钮数量</li>\n<li>支持禁用、隐藏状态</li>\n<li>支持自定义按钮渲染</li>\n<li>支持禁用按钮的工具提示</li>\n</ul>\n<p><strong>适用场景:</strong></p>\n<ul>\n<li>操作栏、工具栏</li>\n<li>表格操作列</li>\n<li>面板标题栏</li>\n<li>任何需要自适应按钮布局的场景</li>\n</ul>\n<h3>LoadingButton</h3>\n<p>封装了加载状态的按钮组件,简化了异步操作的处理。通过内置的状态管理,在异步操作执行期间自动显示加载状态,提升用户体验。同时提供了 useLoading hook,方便在其他组件中复用加载状态管理逻辑。</p>\n<p><strong>主要特性:</strong></p>\n<ul>\n<li>自动管理加载状态</li>\n<li>支持自定义加载文案</li>\n<li>自动处理错误情况</li>\n<li>支持 loading 属性手动控制</li>\n<li>提供的 useLoading Hook 可在其他组件使用</li>\n</ul>\n<p><strong>适用场景:</strong></p>\n<ul>\n<li>表单提交按钮</li>\n<li>数据导出按钮</li>\n<li>任何需要异步操作的按钮</li>\n<li>非按钮组件的异步状态管理</li>\n</ul>\n<h3>ConfirmButton</h3>\n<p>带有确认功能的按钮组件,支持弹窗确认(Popconfirm)和模态框确认(Modal)两种模式。适用于需要用户二次确认的操作,如删除、提交等重要操作。同时提供了 ConfirmLink 和 ConfirmText 变体,以及 withConfirm 高阶组件,满足不同场景的确认需求。</p>\n<p><strong>主要特性:</strong></p>\n<ul>\n<li>支持 Popconfirm 和 Modal 两种确认模式</li>\n<li>支持危险操作样式(红色按钮)</li>\n<li>可自定义确认和取消按钮文案</li>\n<li>提供 ConfirmLink 和 ConfirmText 变体</li>\n<li>确认时自动显示加载状态</li>\n</ul>\n<p><strong>适用场景:</strong></p>\n<ul>\n<li>删除操作</li>\n<li>数据提交</li>\n<li>审核操作</li>\n<li>表格行操作(使用 ConfirmLink/ConfirmText)</li>\n<li>任何需要用户二次确认的操作</li>\n</ul>\n<h3>FetchButton</h3>\n<p>集成了数据请求功能的按钮组件,基于 @kne/react-fetch 库实现。可以直接处理 API 请求,并在请求过程中自动管理加载状态,简化了数据交互的实现。</p>\n<p><strong>主要特性:</strong></p>\n<ul>\n<li>自动管理请求加载状态</li>\n<li>支持请求成功/失败回调</li>\n<li>支持参数传递</li>\n<li>支持请求拦截(beforeFetch)</li>\n<li>基于 @kne/react-fetch 实现</li>\n</ul>\n<p><strong>适用场景:</strong></p>\n<ul>\n<li>数据刷新按钮</li>\n<li>文件导出按钮</li>\n<li>API 请求按钮</li>\n<li>任何按钮触发的数据请求场景</li>\n</ul>\n<h3>ButtonFooter</h3>\n<p>页面底部按钮区域组件,可以自动计算高度并设置 CSS 变量,方便页面布局和样式调整。在小屏幕下,会自动将内容渲染到 body,确保按钮始终可见。</p>\n<p><strong>主要特性:</strong></p>\n<ul>\n<li>自动计算高度并设置 CSS 变量</li>\n<li>响应式设计,小屏幕下固定到底部</li>\n<li>支持多种布局方式(居中、左右分布等)</li>\n<li>适用于表单页面的底部操作区</li>\n</ul>\n<p><strong>适用场景:</strong></p>\n<ul>\n<li>表单页面底部操作按钮</li>\n<li>详情页面底部操作按钮</li>\n<li>对话框底部按钮</li>\n<li>任何需要固定在底部的操作按钮区域</li>\n</ul>\n<h2>组件关系</h2>\n<pre><code>ButtonGroup (自适应布局)\n ├── LoadingButton (加载状态)\n ├── ConfirmButton (确认功能)\n │ ├── ConfirmLink (链接变体)\n │ └── ConfirmText (文本变体)\n └── FetchButton (数据请求)\n └── 基于 LoadingButton\n\nButtonFooter (底部固定区域)\n</code></pre>\n<h2>设计理念</h2>\n<p>该组件库的设计理念是通过封装常见的按钮交互模式,提供开箱即用的解决方案,同时保持足够的灵活性和可扩展性:</p>\n<ol>\n<li>\n<p><strong>关注点分离</strong>:每个组件专注于解决特定的问题,如 ButtonGroup 专注于布局,LoadingButton 专注于状态管理。</p>\n</li>\n<li>\n<p><strong>组合优于继承</strong>:通过组合不同的功能组件,可以实现复杂的交互需求,如 FetchButton 就是 LoadingButton 与数据请求功能的组合。</p>\n</li>\n<li>\n<p><strong>声明式 API</strong>:提供简洁明了的 API,使开发者能够以声明式的方式描述 UI 和交互行为。</p>\n</li>\n<li>\n<p><strong>渐进式增强</strong>:基础组件可以独立使用,也可以与其他组件组合使用,实现更复杂的功能。</p>\n</li>\n<li>\n<p><strong>用户体验优先</strong>:注重细节,如自适应布局、加载状态反馈等,提升最终用户的使用体验。</p>\n</li>\n</ol>\n<h2>特性总结</h2>\n<ul>\n<li><strong>自适应布局</strong>:根据容器宽度自动调整按钮显示方式</li>\n<li><strong>加载状态管理</strong>:简化异步操作的加载状态处理</li>\n<li><strong>操作确认</strong>:提供多种确认模式,增强用户操作安全性</li>\n<li><strong>数据请求集成</strong>:简化按钮与后端 API 的交互</li>\n<li><strong>国际化支持</strong>:内置中英文语言包</li>\n<li><strong>高度可定制</strong>:组件提供丰富的配置选项</li>\n<li><strong>响应式设计</strong>:适配不同屏幕尺寸</li>\n<li><strong>TypeScript 友好</strong>:完整的类型定义</li>\n</ul>`,\n \n \n api: `<p>自适应按钮组组件,能够根据容器宽度自动调整显示的按钮数量,并将多余的按钮放入下拉菜单中。</p>\n<h3>属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>list</td>\n<td>Array<object | function></td>\n<td>[]</td>\n<td>按钮列表,可以是配置对象或渲染函数</td>\n</tr>\n<tr>\n<td>compact</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否使用紧凑模式(Space.Compact)</td>\n</tr>\n<tr>\n<td>showLength</td>\n<td>number</td>\n<td>-</td>\n<td>指定显示的按钮数量,不指定则自动计算</td>\n</tr>\n<tr>\n<td>more</td>\n<td>ReactNode</td>\n<td>-</td>\n<td>自定义\"更多\"按钮</td>\n</tr>\n<tr>\n<td>moreType</td>\n<td>'default' | 'link'</td>\n<td>'default'</td>\n<td>更多按钮类型</td>\n</tr>\n<tr>\n<td>getPopupContainer</td>\n<td>function</td>\n<td>-</td>\n<td>下拉菜单渲染父节点</td>\n</tr>\n<tr>\n<td>trigger</td>\n<td>string</td>\n<td>-</td>\n<td>下拉菜单触发方式</td>\n</tr>\n<tr>\n<td>itemClassName</td>\n<td>string</td>\n<td>-</td>\n<td>按钮项的自定义类名</td>\n</tr>\n<tr>\n<td>...SpaceProps</td>\n<td>-</td>\n<td>-</td>\n<td>Space 组件的其他属性(size、split、align、style等)</td>\n</tr>\n</tbody>\n</table>\n<h3>list 配置项</h3>\n<p>当 list 项为对象时,支持以下属性:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>-</td>\n<td>按钮内容</td>\n</tr>\n<tr>\n<td>type</td>\n<td>string</td>\n<td>-</td>\n<td>按钮类型(primary、default、dashed、link、text)</td>\n</tr>\n<tr>\n<td>disabled</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否禁用</td>\n</tr>\n<tr>\n<td>hidden</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否隐藏</td>\n</tr>\n<tr>\n<td>confirm</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否需要确认</td>\n</tr>\n<tr>\n<td>message</td>\n<td>string | ReactNode</td>\n<td>-</td>\n<td>确认提示内容(设置后会自动使用 ConfirmButton)</td>\n</tr>\n<tr>\n<td>isDelete</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否为删除操作(红色按钮)</td>\n</tr>\n<tr>\n<td>isModal</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否使用模态框确认(在下拉菜单中自动启用)</td>\n</tr>\n<tr>\n<td>buttonComponent</td>\n<td>ReactComponent</td>\n<td>-</td>\n<td>自定义按钮组件</td>\n</tr>\n<tr>\n<td>tooltipProps</td>\n<td>object</td>\n<td>-</td>\n<td>Tooltip 组件属性(禁用时显示提示)</td>\n</tr>\n<tr>\n<td>...ButtonProps</td>\n<td>-</td>\n<td>-</td>\n<td>Button 组件的其他属性</td>\n</tr>\n</tbody>\n</table>\n<p>当 list 项为函数时,函数签名为:</p>\n<pre><code class=\"language-typescript\">(props: { key: number; className: string }, context: { isDropdown: boolean }) => ReactNode\n</code></pre>\n<hr>\n<h2>LoadingButton</h2>\n<p>封装了加载状态的按钮组件,简化异步操作的处理。</p>\n<h3>属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>onClick</td>\n<td>function | Promise</td>\n<td>-</td>\n<td>点击按钮时的回调函数,可以返回 Promise</td>\n</tr>\n<tr>\n<td>loading</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否显示加载状态</td>\n</tr>\n<tr>\n<td>disabled</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否禁用按钮</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode | function</td>\n<td>-</td>\n<td>按钮内容,可以是函数接收 loading 状态</td>\n</tr>\n<tr>\n<td>...ButtonProps</td>\n<td>-</td>\n<td>-</td>\n<td>Button 组件的其他属性</td>\n</tr>\n</tbody>\n</table>\n<h3>useLoading Hook</h3>\n<p>用于管理异步操作加载状态的 Hook。</p>\n<h4>参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>callback</td>\n<td>function</td>\n<td>-</td>\n<td>异步回调函数</td>\n</tr>\n</tbody>\n</table>\n<h4>返回值</h4>\n<table>\n<thead>\n<tr>\n<th>名称</th>\n<th>类型</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>isLoading</td>\n<td>boolean</td>\n<td>当前加载状态</td>\n</tr>\n<tr>\n<td>setIsLoading</td>\n<td>function</td>\n<td>设置加载状态的函数</td>\n</tr>\n<tr>\n<td>callback</td>\n<td>function</td>\n<td>包装后的回调函数</td>\n</tr>\n</tbody>\n</table>\n<hr>\n<h2>ConfirmButton</h2>\n<p>带有确认功能的按钮组件,支持弹窗确认和模态框确认两种模式。</p>\n<h3>属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>-</td>\n<td>按钮内容</td>\n</tr>\n<tr>\n<td>onClick</td>\n<td>function | Promise</td>\n<td>-</td>\n<td>确认后的回调函数,可以返回 Promise</td>\n</tr>\n<tr>\n<td>title</td>\n<td>string | ReactNode</td>\n<td>-</td>\n<td>确认框标题</td>\n</tr>\n<tr>\n<td>message</td>\n<td>string | ReactNode</td>\n<td>-</td>\n<td>确认框内容</td>\n</tr>\n<tr>\n<td>okText</td>\n<td>string</td>\n<td>-</td>\n<td>确认按钮文字(默认根据 isDelete 动态显示)</td>\n</tr>\n<tr>\n<td>cancelText</td>\n<td>string</td>\n<td>-</td>\n<td>取消按钮文字</td>\n</tr>\n<tr>\n<td>isModal</td>\n<td>boolean</td>\n<td>false</td>\n<td>是否使用模态框确认(默认为 Popconfirm)</td>\n</tr>\n<tr>\n<td>isDelete</td>\n<td>boolean</td>\n<td>true</td>\n<td>是否为删除操作(红色按钮、确认按钮)</td>\n</tr>\n<tr>\n<td>showCancel</td>\n<td>boolean</td>\n<td>true</td>\n<td>是否显示取消按钮</td>\n</tr>\n<tr>\n<td>placement</td>\n<td>string</td>\n<td>-</td>\n<td>Popconfirm 的位置</td>\n</tr>\n<tr>\n<td>getContainer</td>\n<td>function</td>\n<td>-</td>\n<td>确认框渲染容器</td>\n</tr>\n<tr>\n<td>renderModal</td>\n<td>function</td>\n<td>-</td>\n<td>自定义 Modal 渲染函数</td>\n</tr>\n<tr>\n<td>onCancel</td>\n<td>function</td>\n<td>-</td>\n<td>取消按钮的回调</td>\n</tr>\n<tr>\n<td>...ButtonProps</td>\n<td>-</td>\n<td>-</td>\n<td>Button 组件的其他属性</td>\n</tr>\n</tbody>\n</table>\n<h3>ConfirmLink</h3>\n<p>ConfirmButton 的链接样式变体。</p>\n<h3>ConfirmText</h3>\n<p>ConfirmButton 的纯文本样式变体。</p>\n<h3>withConfirm</h3>\n<p>高阶组件,用于为任意组件添加确认功能。</p>\n<blockquote>\n<p>⚠️ 该 API 已标记为废弃,后续版本可能删除,建议不要使用。</p>\n</blockquote>\n<hr>\n<h2>FetchButton</h2>\n<p>集成了数据请求功能的按钮组件,基于 @kne/react-fetch 库实现。</p>\n<h3>属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>object | function</td>\n<td>-</td>\n<td>请求 API 配置</td>\n</tr>\n<tr>\n<td>params</td>\n<td>object</td>\n<td>-</td>\n<td>请求参数</td>\n</tr>\n<tr>\n<td>onSuccess</td>\n<td>function</td>\n<td>-</td>\n<td>请求成功回调,参数为 <code>{ data }</code></td>\n</tr>\n<tr>\n<td>onError</td>\n<td>function</td>\n<td>-</td>\n<td>请求失败回调</td>\n</tr>\n<tr>\n<td>beforeFetch</td>\n<td>function</td>\n<td>-</td>\n<td>请求前处理函数,返回 false 可阻止请求</td>\n</tr>\n<tr>\n<td>afterFetch</td>\n<td>function</td>\n<td>-</td>\n<td>请求后处理函数</td>\n</tr>\n<tr>\n<td>fetchOptions</td>\n<td>object</td>\n<td>-</td>\n<td>传递给 fetch 函数的选项</td>\n</tr>\n<tr>\n<td>onClick</td>\n<td>function</td>\n<td>-</td>\n<td>请求成功后的回调(与 onSuccess 相同)</td>\n</tr>\n<tr>\n<td>...LoadingButtonProps</td>\n<td>-</td>\n<td>-</td>\n<td>LoadingButton 组件的其他属性</td>\n</tr>\n</tbody>\n</table>\n<h3>api 配置</h3>\n<p>api 可以是对象或函数:</p>\n<pre><code class=\"language-typescript\">// 对象形式\napi: {\n loader: async ({ params }) => {\n return { data: 'response data' };\n }\n}\n\n// 函数形式\napi: async ({ params }) => {\n return { data: 'response data' };\n}\n</code></pre>\n<hr>\n<h2>ButtonFooter</h2>\n<p>页面底部按钮区域组件,可以自动计算高度并设置 CSS 变量。</p>\n<h3>属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>-</td>\n<td>按钮区域内容</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>-</td>\n<td>容器的自定义类名</td>\n</tr>\n<tr>\n<td>innerClassName</td>\n<td>string</td>\n<td>-</td>\n<td>内部容器的自定义类名</td>\n</tr>\n<tr>\n<td>target</td>\n<td>HTMLElement</td>\n<td>document.body</td>\n<td>移动端渲染的目标容器</td>\n</tr>\n</tbody>\n</table>\n<h3>特性</h3>\n<ul>\n<li>在小屏幕(≤768px)下,会将内容使用 Portal 渲染到 body</li>\n<li>自动计算高度并设置 CSS 变量</li>\n<li>适用于固定在页面底部的操作按钮区域</li>\n</ul>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `ButtonGroup 基础用法`,\n description: `ButtonGroup 能够根据容器宽度自动调整显示的按钮数量,并将多余的按钮放入下拉菜单中。适用于操作栏、工具栏等场景。`,\n code: `const { default: ButtonGroup } = _ButtonGroup;\nconst { Flex, Button, Space, Typography } = antd;\nconst { useState } = React;\nconst { Text } = Typography;\n\n// 基础用法 - 自动适应容器宽度\nconst BasicExample = () => {\n const [width, setWidth] = useState(300);\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">调整容器宽度查看自适应效果</Text>\n <Flex gap={8}>\n <div style={{ width: \\`\\${width}px\\`, padding: '12px', background: '#f5f5f5', borderRadius: '8px' }}>\n <ButtonGroup\n list={[\n { type: 'primary', children: '新建' },\n { type: 'default', children: '编辑' },\n { type: 'default', children: '导出' },\n { type: 'default', children: '打印' },\n { children: '更多操作1', isDelete: false, message: '确定执行吗?' },\n { children: '更多操作2', message: '确定执行吗?' },\n { children: '删除', isDelete: true }\n ]}\n />\n </div>\n </Flex>\n <Space>\n <Button onClick={() => setWidth(w => Math.max(200, w - 50))}>减少宽度</Button>\n <Button onClick={() => setWidth(w => Math.min(600, w + 50))}>增加宽度</Button>\n </Space>\n </Flex>\n );\n};\n\n// 紧凑模式\nconst CompactExample = () => {\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">紧凑模式(适用于工具栏)</Text>\n <ButtonGroup compact list={[{ type: 'primary', children: '保存' }, { children: '撤销' }, { children: '重做' }, { children: '删除', isDelete: true }]} />\n </Flex>\n );\n};\n\n// 链接样式 - 更多按钮\nconst LinkStyleExample = () => {\n const [width, setWidth] = useState(200);\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">链接样式(适用于表格操作栏)</Text>\n <div style={{ width: \\`\\${width}px\\` }}>\n <ButtonGroup\n moreType=\"link\"\n list={[\n { children: '查看', type: 'link' },\n { children: '编辑', type: 'link' },\n { children: '删除', type: 'link', isDelete: true, message: '确定删除吗?' },\n { children: '审核', type: 'link' },\n { children: '驳回', type: 'link' }\n ]}\n />\n </div>\n <Space>\n <Button onClick={() => setWidth(w => Math.max(150, w - 30))}>-</Button>\n <Button onClick={() => setWidth(w => Math.min(400, w + 30))}>+</Button>\n </Space>\n </Flex>\n );\n};\n\n// 指定显示数量\nconst FixedLengthExample = () => {\n const [showLength, setShowLength] = useState(2);\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">指定显示按钮数量(showLength)</Text>\n <Space>\n <Button type={showLength === 1 ? 'primary' : 'default'} onClick={() => setShowLength(1)}>\n 显示1个\n </Button>\n <Button type={showLength === 2 ? 'primary' : 'default'} onClick={() => setShowLength(2)}>\n 显示2个\n </Button>\n <Button type={showLength === 3 ? 'primary' : 'default'} onClick={() => setShowLength(3)}>\n 显示3个\n </Button>\n </Space>\n <ButtonGroup showLength={showLength} list={[{ type: 'primary', children: '主要操作' }, { children: '次要操作1' }, { children: '次要操作2' }, { children: '次要操作3' }, { children: '次要操作4' }]} />\n </Flex>\n );\n};\n\n// 自定义渲染函数\nconst CustomRenderExample = () => {\n const CustomButton = props => (\n <Button {...props} style={{ borderRadius: '4px' }}>\n {props.children}\n </Button>\n );\n\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">自定义渲染(支持函数式配置)</Text>\n <div style={{ padding: '12px', background: '#f5f5f5', borderRadius: '8px', width: '280px' }}>\n <ButtonGroup\n moreType=\"link\"\n list={[\n props => (\n <CustomButton {...props} type=\"primary\">\n 自定义按钮\n </CustomButton>\n ),\n props => <CustomButton {...props}>按钮2</CustomButton>,\n props => <CustomButton {...props}>按钮3</CustomButton>,\n props => <CustomButton {...props}>按钮4</CustomButton>\n ]}\n />\n </div>\n </Flex>\n );\n};\n\n// 禁用状态与隐藏\nconst StateExample = () => {\n const [disabled, setDisabled] = useState(true);\n const [hidden, setHidden] = useState(true);\n\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">禁用与隐藏状态</Text>\n <Space>\n <Button onClick={() => setDisabled(!disabled)}>{disabled ? '启用' : '禁用'}操作3</Button>\n <Button onClick={() => setHidden(!hidden)}>{hidden ? '显示' : '隐藏'}操作4</Button>\n </Space>\n <ButtonGroup list={[{ type: 'primary', children: '操作1' }, { children: '操作2' }, { children: '操作3', disabled }, { children: '操作4', hidden }, { children: '操作5', message: '确定吗?' }]} />\n </Flex>\n );\n};\n\n// 工具提示\nconst TooltipExample = () => {\n return (\n <Flex gap={16} vertical>\n <Text type=\"secondary\">禁用按钮提示(tooltipProps)</Text>\n <ButtonGroup\n list={[\n { type: 'primary', children: '可用操作' },\n {\n children: '已禁用操作',\n disabled: true,\n tooltipProps: {\n title: '此操作暂时不可用,请先完成前置步骤',\n placement: 'bottom'\n }\n },\n {\n children: '需要权限',\n disabled: true,\n tooltipProps: {\n title: '您没有执行此操作的权限',\n placement: 'bottom'\n }\n }\n ]}\n />\n </Flex>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\">\n <Typography.Title level={3}>ButtonGroup 自适应按钮组</Typography.Title>\n <Typography.Paragraph>ButtonGroup 是一个自适应按钮组组件,能够根据容器宽度自动调整显示的按钮数量, 多余的按钮会放入下拉菜单中。适用于操作栏、工具栏、表格操作列等场景。</Typography.Paragraph>\n\n <Flex vertical gap={32}>\n <div>\n <Typography.Title level={4}>基础用法</Typography.Title>\n <BasicExample />\n </div>\n\n <div>\n <Typography.Title level={4}>紧凑模式</Typography.Title>\n <CompactExample />\n </div>\n\n <div>\n <Typography.Title level={4}>链接样式</Typography.Title>\n <LinkStyleExample />\n </div>\n\n <div>\n <Typography.Title level={4}>指定显示数量</Typography.Title>\n <FixedLengthExample />\n </div>\n\n <div>\n <Typography.Title level={4}>自定义渲染</Typography.Title>\n <CustomRenderExample />\n </div>\n\n <div>\n <Typography.Title level={4}>禁用与隐藏</Typography.Title>\n <StateExample />\n </div>\n\n <div>\n <Typography.Title level={4}>禁用提示</Typography.Title>\n <TooltipExample />\n </div>\n </Flex>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ButtonGroup\",\n packageName: \"@kne/button-group\",\n importStatement: \"import * as _ButtonGroup from \\\"@kne/button-group\\\"\",\n component: component_36\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_37\n}]\n},{\n title: `LoadingButton 加载按钮`,\n description: `LoadingButton 封装了加载状态,简化异步操作的处理。点击按钮时自动显示加载状态,避免重复提交。`,\n code: `const { LoadingButton, useLoading } = _ButtonGroup;\nconst { Space, Button, Typography, message, Card, Alert, Flex } = antd;\nconst { useState } = React;\n\n// 基础用法 - 自动加载状态\nconst BasicExample = () => {\n const handleClick = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('操作成功!');\n resolve();\n }, 1500);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">点击按钮,自动管理加载状态</Typography.Text>\n <Space wrap>\n <LoadingButton type=\"primary\" onClick={handleClick}>\n 保存数据\n </LoadingButton>\n <LoadingButton onClick={handleClick}>提交审核</LoadingButton>\n <LoadingButton danger onClick={handleClick}>删除</LoadingButton>\n </Space>\n </Space>\n );\n};\n\n// 自定义加载文案\nconst CustomTextExample = () => {\n const handleClick = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('上传完成');\n resolve();\n }, 2000);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">使用函数自定义加载时的文案</Typography.Text>\n <Space>\n <LoadingButton onClick={handleClick}>\n {(isLoading) => (isLoading ? '正在上传...' : '上传文件')}\n </LoadingButton>\n <LoadingButton onClick={handleClick} type=\"primary\">\n {(isLoading) => (isLoading ? '提交中...' : '提交订单')}\n </LoadingButton>\n </Space>\n </Space>\n );\n};\n\n// 错误处理\nconst ErrorExample = () => {\n const [shouldFail, setShouldFail] = useState(false);\n\n const handleClick = () => {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n if (shouldFail) {\n message.error('操作失败,请重试');\n reject(new Error('操作失败'));\n } else {\n message.success('操作成功');\n resolve();\n }\n }, 1000);\n });\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 演示错误处理:加载状态会自动解除\n </Typography.Text>\n <Space>\n <Button onClick={() => setShouldFail(!shouldFail)}>\n {shouldFail ? '切换为成功' : '切换为失败'}\n </Button>\n </Space>\n <Space>\n <LoadingButton onClick={handleClick}>\n {shouldFail ? '会失败的操作' : '会成功的操作'}\n </LoadingButton>\n </Space>\n {shouldFail && <Alert message=\"当前设置为失败模式\" type=\"warning\" />}\n </Space>\n );\n};\n\n// 手动控制加载状态\nconst ManualExample = () => {\n const [loading, setLoading] = useState(false);\n\n const handleClick = () => {\n setLoading(true);\n setTimeout(() => {\n setLoading(false);\n message.success('手动控制加载完成');\n }, 2000);\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">通过 loading 属性手动控制加载状态</Typography.Text>\n <LoadingButton loading={loading} onClick={handleClick}>\n 手动控制加载\n </LoadingButton>\n </Space>\n );\n};\n\n// useLoading Hook 示例\nconst UseLoadingExample = () => {\n const { isLoading, callback } = useLoading(() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('Hook 模式操作完成');\n resolve();\n }, 1500);\n });\n });\n\n return (\n <Card title=\"useLoading Hook\" style={{ width: 400 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 在非按钮组件中使用 useLoading 管理异步状态\n </Typography.Text>\n <Space>\n <Button onClick={callback} loading={isLoading}>\n 使用 Hook\n </Button>\n <Button onClick={() => {}}>\n 独立按钮(不受影响)\n </Button>\n </Space>\n {isLoading && (\n <Alert message=\"当前状态:加载中\" type=\"info\" showIcon />\n )}\n </Space>\n </Card>\n );\n};\n\n// 不同按钮类型\nconst ButtonTypesExample = () => {\n const handleClick = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('完成');\n resolve();\n }, 1000);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">支持所有 Ant Design Button 类型</Typography.Text>\n <Space wrap>\n <LoadingButton type=\"primary\" onClick={handleClick}>Primary</LoadingButton>\n <LoadingButton type=\"default\" onClick={handleClick}>Default</LoadingButton>\n <LoadingButton type=\"dashed\" onClick={handleClick}>Dashed</LoadingButton>\n <LoadingButton type=\"link\" onClick={handleClick}>Link</LoadingButton>\n <LoadingButton type=\"text\" onClick={handleClick}>Text</LoadingButton>\n </Space>\n <Space wrap>\n <LoadingButton type=\"primary\" ghost onClick={handleClick}>Primary Ghost</LoadingButton>\n <LoadingButton type=\"default\" ghost onClick={handleClick}>Default Ghost</LoadingButton>\n </Space>\n </Space>\n );\n};\n\n// 图标按钮\nconst IconExample = () => {\n const handleClick = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('操作完成');\n resolve();\n }, 1200);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">支持图标</Typography.Text>\n <Space>\n <LoadingButton type=\"primary\" icon={<span>⬆️</span>} onClick={handleClick}>\n 上传\n </LoadingButton>\n <LoadingButton icon={<span>⬇️</span>} onClick={handleClick}>\n 下载\n </LoadingButton>\n <LoadingButton danger icon={<span>🗑️</span>} onClick={handleClick}>\n 删除\n </LoadingButton>\n </Space>\n </Space>\n );\n};\n\n// 实际应用场景 - 表单提交\nconst FormSubmitExample = () => {\n const handleSubmit = async () => {\n // 模拟表单验证\n await new Promise(resolve => setTimeout(resolve, 500));\n // 模拟 API 请求\n await new Promise((resolve) => {\n setTimeout(() => {\n message.success('表单提交成功!');\n resolve();\n }, 1500);\n });\n };\n\n return (\n <Card title=\"表单提交场景\" style={{ width: 400 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 点击提交按钮,自动防止重复提交\n </Typography.Text>\n <Space>\n <LoadingButton type=\"primary\" onClick={handleSubmit}>\n 提交表单\n </LoadingButton>\n <Button onClick={() => message.info('已取消')}>取消</Button>\n </Space>\n </Space>\n </Card>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\">\n <Typography.Title level={3}>LoadingButton 加载按钮</Typography.Title>\n <Typography.Paragraph>\n LoadingButton 封装了加载状态,简化异步操作的处理。点击按钮时自动显示加载状态,\n 避免重复提交,同时提供 useLoading Hook 供其他组件使用。\n </Typography.Paragraph>\n\n <Flex vertical gap={32}>\n <div>\n <Typography.Title level={4}>基础用法</Typography.Title>\n <BasicExample />\n </div>\n\n <div>\n <Typography.Title level={4}>自定义加载文案</Typography.Title>\n <CustomTextExample />\n </div>\n\n <div>\n <Typography.Title level={4}>错误处理</Typography.Title>\n <ErrorExample />\n </div>\n\n <div>\n <Typography.Title level={4}>手动控制加载状态</Typography.Title>\n <ManualExample />\n </div>\n\n <div>\n <Typography.Title level={4}>useLoading Hook</Typography.Title>\n <UseLoadingExample />\n </div>\n\n <div>\n <Typography.Title level={4}>不同按钮类型</Typography.Title>\n <ButtonTypesExample />\n </div>\n\n <div>\n <Typography.Title level={4}>图标按钮</Typography.Title>\n <IconExample />\n </div>\n\n <div>\n <Typography.Title level={4}>实际应用场景</Typography.Title>\n <FormSubmitExample />\n </div>\n </Flex>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ButtonGroup\",\n packageName: \"@kne/button-group\",\n importStatement: \"import * as _ButtonGroup from \\\"@kne/button-group\\\"\",\n component: component_36\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_37\n}]\n},{\n title: `ConfirmButton 确认按钮`,\n description: `ConfirmButton 带有确认功能,支持弹窗确认和模态框确认两种模式。适用于删除、提交等重要操作。`,\n code: `const { ConfirmButton, ConfirmLink, ConfirmText } = _ButtonGroup;\nconst { Flex, Space, Typography, message, Card, List, Tag, Button } = antd;\nconst { useState } = React;\n\n// 基础用法 - Popconfirm 模式\nconst BasicExample = () => {\n const handleDelete = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('删除成功');\n resolve();\n }, 500);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">\n Popconfirm 模式(气泡确认框),适用于快速确认\n </Typography.Text>\n <Space>\n <ConfirmButton message=\"确定要删除吗?\" onClick={handleDelete}>\n 删除\n </ConfirmButton>\n <ConfirmButton message=\"确定要提交吗?\" onClick={handleDelete}>\n 提交\n </ConfirmButton>\n </Space>\n </Space>\n );\n};\n\n// Modal 模式\nconst ModalExample = () => {\n const handleSubmit = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('提交成功');\n resolve();\n }, 500);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">\n Modal 模式(模态框),适用于重要操作或长内容提示\n </Typography.Text>\n <Space>\n <ConfirmButton\n isModal\n message=\"此操作将永久删除该数据,删除后无法恢复。确定要继续吗?\"\n onClick={handleSubmit}\n >\n 删除数据\n </ConfirmButton>\n <ConfirmButton\n isModal\n title=\"提交确认\"\n message=\"提交后数据将进入审核流程,确认要提交吗?\"\n onClick={handleSubmit}\n >\n 提交审核\n </ConfirmButton>\n </Space>\n </Space>\n );\n};\n\n// 危险操作样式\nconst DangerExample = () => {\n const handleDelete = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('已删除');\n resolve();\n }, 500);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">\n 使用 isDelete 标识危险操作(红色按钮)\n </Typography.Text>\n <Space>\n <ConfirmButton\n danger\n message=\"确定删除吗?\"\n onClick={handleDelete}\n >\n 普通按钮\n </ConfirmButton>\n <ConfirmButton\n isDelete\n message=\"确定删除吗?\"\n onClick={handleDelete}\n >\n 删除按钮\n </ConfirmButton>\n <ConfirmButton\n isDelete\n isModal\n message=\"此操作无法撤销,确定要继续吗?\"\n onClick={handleDelete}\n >\n 删除(Modal)\n </ConfirmButton>\n </Space>\n </Space>\n );\n};\n\n// 自定义确认文案\nconst CustomTextExample = () => {\n const handleAction = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('操作完成');\n resolve();\n }, 500);\n });\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">自定义确认和取消按钮文案</Typography.Text>\n <Space>\n <ConfirmButton\n message=\"确定要执行此操作吗?\"\n okText=\"确认执行\"\n cancelText=\"暂不执行\"\n onClick={handleAction}\n >\n 自定义文案\n </ConfirmButton>\n <ConfirmButton\n isModal\n title=\"操作确认\"\n message=\"请确认是否继续执行此操作\"\n okText=\"是,继续\"\n cancelText=\"否,取消\"\n onClick={handleAction}\n >\n Modal 自定义文案\n </ConfirmButton>\n </Space>\n </Space>\n );\n};\n\n// ConfirmLink 和 ConfirmText\nconst LinkAndTextExample = () => {\n const handleAction = () => {\n message.success('操作成功');\n return Promise.resolve();\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n ConfirmLink 和 ConfirmText 变体,适用于表格行操作等场景\n </Typography.Text>\n <List\n bordered\n style={{ width: 400 }}\n dataSource={[\n { id: 1, name: '数据项 A', status: '已提交' },\n { id: 2, name: '数据项 B', status: '草稿' },\n { id: 3, name: '数据项 C', status: '已审核' }\n ]}\n renderItem={(item) => (\n <List.Item\n actions={[\n <ConfirmLink key=\"edit\" message=\"确定编辑吗?\" onClick={handleAction}>\n 编辑\n </ConfirmLink>,\n <ConfirmLink key=\"delete\" isDelete message=\"确定删除吗?\" onClick={handleAction}>\n 删除\n </ConfirmLink>\n ]}\n >\n <List.Item.Meta\n title={item.name}\n description={<Tag color={item.status === '已提交' ? 'blue' : 'default'}>{item.status}</Tag>}\n />\n </List.Item>\n )}\n />\n <Space>\n <ConfirmText onClick={handleAction}>纯文本确认</ConfirmText>\n <Typography.Text type=\"secondary\">|</Typography.Text>\n <ConfirmText isDelete onClick={handleAction}>删除</ConfirmText>\n </Space>\n </Space>\n );\n};\n\n// 禁用状态\nconst DisabledExample = () => {\n const [disabled, setDisabled] = useState(true);\n const handleDelete = () => {\n message.success('已删除');\n return Promise.resolve();\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">禁用状态下不会触发确认</Typography.Text>\n <Space>\n <Button onClick={() => setDisabled(!disabled)}>\n {disabled ? '启用' : '禁用'}\n </Button>\n </Space>\n <Space>\n <ConfirmButton disabled={disabled} message=\"确定删除吗?\" onClick={handleDelete}>\n 删除\n </ConfirmButton>\n <ConfirmLink disabled={disabled} message=\"确定删除吗?\" onClick={handleDelete}>\n 删除\n </ConfirmLink>\n </Space>\n </Space>\n );\n};\n\n// 实际应用场景 - 表格操作\nconst TableActionExample = () => {\n const handleEdit = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('进入编辑模式');\n resolve();\n }, 300);\n });\n };\n\n const handleDelete = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('已删除');\n resolve();\n }, 300);\n });\n };\n\n const handleAudit = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success('审核通过');\n resolve();\n }, 300);\n });\n };\n\n return (\n <Card title=\"实际应用:表格操作栏\" style={{ width: 500 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 模拟表格中的操作按钮,包含不同的确认方式\n </Typography.Text>\n <List\n bordered\n dataSource={[\n { id: 1, name: '产品 A', price: '¥99.00' },\n { id: 2, name: '产品 B', price: '¥199.00' }\n ]}\n renderItem={(item) => (\n <List.Item\n actions={[\n <ConfirmButton key=\"edit\" type=\"link\" message={\\`确定编辑 \\${item.name} 吗?\\`} onClick={handleEdit}>\n 编辑\n </ConfirmButton>,\n <ConfirmButton key=\"audit\" type=\"link\" message={\\`确定通过 \\${item.name} 的审核吗?\\`} onClick={handleAudit}>\n 审核\n </ConfirmButton>,\n <ConfirmButton\n key=\"delete\"\n type=\"link\"\n danger\n message={\\`确定删除 \\${item.name} 吗?此操作无法撤销。\\`}\n onClick={handleDelete}\n >\n 删除\n </ConfirmButton>\n ]}\n >\n <List.Item.Meta\n title={item.name}\n description={item.price}\n />\n </List.Item>\n )}\n />\n </Space>\n </Card>\n );\n};\n\n// 批量操作\nconst BatchExample = () => {\n const [selectedCount, setSelectedCount] = useState(0);\n const handleBatchDelete = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success(\\`已删除 \\${selectedCount} 条数据\\`);\n setSelectedCount(0);\n resolve();\n }, 500);\n });\n };\n\n return (\n <Card title=\"批量操作场景\" style={{ width: 450 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <Typography.Text type=\"secondary\">已选择:</Typography.Text>\n <Typography.Text strong>{selectedCount} 项</Typography.Text>\n <Button size=\"small\" onClick={() => setSelectedCount(Math.floor(Math.random() * 10))}>\n 随机选择\n </Button>\n </Space>\n <Space>\n <ConfirmButton\n type=\"primary\"\n disabled={selectedCount === 0}\n isModal\n title=\"批量删除确认\"\n message={\\`确定要删除选中的 \\${selectedCount} 条数据吗?此操作无法撤销。\\`}\n onClick={handleBatchDelete}\n >\n 批量删除\n </ConfirmButton>\n <ConfirmButton\n disabled={selectedCount === 0}\n message={\\`确定导出选中的 \\${selectedCount} 条数据吗?\\`}\n onClick={() => {\n message.success(\\`正在导出 \\${selectedCount} 条数据\\`);\n return Promise.resolve();\n }}\n >\n 导出\n </ConfirmButton>\n </Space>\n </Space>\n </Card>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\">\n <Typography.Title level={3}>ConfirmButton 确认按钮</Typography.Title>\n <Typography.Paragraph>\n ConfirmButton 提供确认功能,支持 Popconfirm(气泡确认框)和 Modal(模态框)两种模式。\n 还提供 ConfirmLink 和 ConfirmText 变体,以及 withConfirm 高阶组件。\n </Typography.Paragraph>\n\n <Flex vertical gap={32}>\n <div>\n <Typography.Title level={4}>Popconfirm 模式</Typography.Title>\n <BasicExample />\n </div>\n\n <div>\n <Typography.Title level={4}>Modal 模式</Typography.Title>\n <ModalExample />\n </div>\n\n <div>\n <Typography.Title level={4}>危险操作样式</Typography.Title>\n <DangerExample />\n </div>\n\n <div>\n <Typography.Title level={4}>自定义文案</Typography.Title>\n <CustomTextExample />\n </div>\n\n <div>\n <Typography.Title level={4}>Link 和 Text 变体</Typography.Title>\n <LinkAndTextExample />\n </div>\n\n <div>\n <Typography.Title level={4}>禁用状态</Typography.Title>\n <DisabledExample />\n </div>\n\n <div>\n <Typography.Title level={4}>实际应用场景</Typography.Title>\n <TableActionExample />\n </div>\n\n <div>\n <Typography.Title level={4}>批量操作</Typography.Title>\n <BatchExample />\n </div>\n </Flex>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ButtonGroup\",\n packageName: \"@kne/button-group\",\n importStatement: \"import * as _ButtonGroup from \\\"@kne/button-group\\\"\",\n component: component_36\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_37\n}]\n},{\n title: `FetchButton 请求按钮`,\n description: `FetchButton 集成了数据请求功能,自动管理加载状态和请求流程。适用于按钮触发 API 请求的场景。`,\n code: `const { FetchButton } = _ButtonGroup;\nconst { Space, Typography, message, Card, Alert, Form, Input, Select, Button, Flex } = antd;\nconst { useState } = React;\n\n// 基础用法\nconst BasicExample = () => {\n const handleSuccess = ({ data }) => {\n message.success(\\`获取数据成功: \\${data}\\`);\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 点击按钮触发 API 请求,自动管理加载状态\n </Typography.Text>\n <FetchButton\n type=\"primary\"\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: '用户信息数据' });\n }, 1500);\n });\n }\n }}\n onClick={handleSuccess}\n >\n 获取用户信息\n </FetchButton>\n </Space>\n );\n};\n\n// 带参数请求\nconst WithParamsExample = () => {\n const [userId, setUserId] = useState('1');\n\n const handleSuccess = ({ data }) => {\n message.success(\\`获取成功: \\${JSON.stringify(data)}\\`);\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">传递参数到 API 请求</Typography.Text>\n <Space>\n <Select\n value={userId}\n onChange={setUserId}\n style={{ width: 120 }}\n options={[\n { value: '1', label: '用户1' },\n { value: '2', label: '用户2' },\n { value: '3', label: '用户3' }\n ]}\n />\n <FetchButton\n params={{ userId }}\n api={{\n loader: async ({ params }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: { userId: params.userId, name: \\`用户\\${params.userId}\\`, role: '管理员' } });\n }, 1000);\n });\n }\n }}\n onClick={handleSuccess}\n >\n 获取用户详情\n </FetchButton>\n </Space>\n </Space>\n );\n};\n\n// 成功和失败回调\nconst CallbackExample = () => {\n const [status, setStatus] = useState('');\n const [shouldFail, setShouldFail] = useState(false);\n\n const handleSuccess = ({ data }) => {\n setStatus('success');\n message.success('数据加载成功');\n console.log('成功数据:', data);\n };\n\n const handleError = (error) => {\n setStatus('error');\n message.error('数据加载失败');\n console.error('错误信息:', error);\n };\n\n return (\n <Card title=\"成功与失败回调\" style={{ width: 450 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <Button onClick={() => setShouldFail(!shouldFail)} size=\"small\">\n {shouldFail ? '切换为成功' : '切换为失败'}\n </Button>\n </Space>\n <FetchButton\n type=\"primary\"\n api={{\n loader: async () => {\n return new Promise((resolve, reject) => {\n setTimeout(() => {\n if (shouldFail) {\n reject(new Error('模拟的请求失败'));\n } else {\n resolve({ data: { message: '请求成功', timestamp: Date.now() } });\n }\n }, 1000);\n });\n }\n }}\n onSuccess={handleSuccess}\n onError={handleError}\n >\n {shouldFail ? '失败请求' : '成功请求'}\n </FetchButton>\n {status === 'success' && <Alert message=\"上次请求:成功\" type=\"success\" />}\n {status === 'error' && <Alert message=\"上次请求:失败\" type=\"error\" />}\n </Space>\n </Card>\n );\n};\n\n// 导出文件场景\nconst ExportExample = () => {\n const handleExport = ({ data }) => {\n message.success(\\`导出成功: \\${data.url}\\`);\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">模拟文件导出场景</Typography.Text>\n <Space>\n <FetchButton\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: { url: '/download/report.xlsx', size: '2.5MB' } });\n }, 2000);\n });\n }\n }}\n onClick={handleExport}\n >\n 导出报表\n </FetchButton>\n <FetchButton\n type=\"primary\"\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: { url: '/download/data.csv', size: '1.2MB' } });\n }, 1500);\n });\n }\n }}\n onClick={handleExport}\n >\n 导出 CSV\n </FetchButton>\n </Space>\n </Space>\n );\n};\n\n// 表单提交场景\nconst FormSubmitExample = () => {\n const [form] = Form.useForm();\n const [loading, setLoading] = useState(false);\n const [submittedData, setSubmittedData] = useState(null);\n\n const handleSubmit = ({ data }) => {\n setSubmittedData(data);\n message.success('表单提交成功');\n };\n\n const onFinish = async () => {\n try {\n const values = await form.validateFields();\n setLoading(true);\n // 使用 FetchButton 内部处理,这里只是演示\n await new Promise(resolve => setTimeout(resolve, 1000));\n setLoading(false);\n message.success('验证通过');\n } catch (error) {\n message.error('请检查表单内容');\n }\n };\n\n return (\n <Card title=\"表单提交场景\" style={{ width: 450 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Form\n form={form}\n layout=\"vertical\"\n >\n <Form.Item\n name=\"username\"\n label=\"用户名\"\n rules={[{ required: true, message: '请输入用户名' }]}\n >\n <Input placeholder=\"请输入用户名\" />\n </Form.Item>\n <Form.Item\n name=\"email\"\n label=\"邮箱\"\n rules={[{ required: true, message: '请输入邮箱' }]}\n >\n <Input placeholder=\"请输入邮箱\" />\n </Form.Item>\n </Form>\n <Space>\n <FetchButton\n type=\"primary\"\n api={{\n loader: async ({ params }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: { id: 123, ...params, createTime: new Date().toISOString() } });\n }, 1500);\n });\n }\n }}\n beforeFetch={() => {\n const values = form.getFieldsValue();\n if (!values.username || !values.email) {\n message.error('请填写完整信息');\n return false;\n }\n return true;\n }}\n onClick={handleSubmit}\n >\n 提交表单\n </FetchButton>\n <Button onClick={() => form.resetFields()}>重置</Button>\n </Space>\n {submittedData && (\n <Alert\n message=\"提交成功\"\n description={JSON.stringify(submittedData, null, 2)}\n type=\"success\"\n />\n )}\n </Space>\n </Card>\n );\n};\n\n// 刷新数据场景\nconst RefreshExample = () => {\n const [data, setData] = useState(null);\n const [lastRefresh, setLastRefresh] = useState(null);\n\n const handleRefresh = ({ data: newData }) => {\n console.log(newData);\n setData(newData);\n setLastRefresh(new Date().toLocaleTimeString());\n message.success('数据已更新');\n };\n\n return (\n <Card title=\"刷新数据场景\" style={{ width: 450 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <Typography.Text type=\"secondary\">上次刷新:</Typography.Text>\n <Typography.Text>{lastRefresh || '从未刷新'}</Typography.Text>\n </Space>\n <FetchButton\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n users: [\n { id: 1, name: '用户A', status: '在线' },\n { id: 2, name: '用户B', status: '离线' },\n { id: 3, name: '用户C', status: '在线' }\n ],\n total: 3\n });\n }, 1000);\n });\n }\n }}\n onClick={handleRefresh}\n >\n 刷新数据\n </FetchButton>\n {data && (\n <Alert\n message={\\`当前数据:\\${data.users?.length} 个用户在线\\`}\n type=\"info\"\n />\n )}\n </Space>\n </Card>\n );\n};\n\n// beforeFetch 拦截\nconst BeforeFetchExample = () => {\n const [allowed, setAllowed] = useState(true);\n\n const handleFetch = ({ data }) => {\n message.success('请求通过');\n };\n\n const beforeFetch = () => {\n if (!allowed) {\n message.warning('请求被 beforeFetch 拦截');\n return false;\n }\n return true;\n };\n\n return (\n <Space direction=\"vertical\">\n <Typography.Text type=\"secondary\">beforeFetch 可以拦截请求</Typography.Text>\n <Space>\n <Button onClick={() => setAllowed(!allowed)} size=\"small\">\n {allowed ? '拦截请求' : '允许请求'}\n </Button>\n </Space>\n <FetchButton\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({ data: '请求成功' });\n }, 800);\n });\n }\n }}\n beforeFetch={beforeFetch}\n onClick={handleFetch}\n >\n {allowed ? '发送请求' : '请求已拦截'}\n </FetchButton>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\">\n <Typography.Title level={3}>FetchButton 请求按钮</Typography.Title>\n <Typography.Paragraph>\n FetchButton 集成了数据请求功能,基于 @kne/react-fetch 库实现。\n 自动管理加载状态,支持成功/失败回调、参数传递、请求拦截等功能。\n </Typography.Paragraph>\n\n <Flex vertical gap={32}>\n <div>\n <Typography.Title level={4}>基础用法</Typography.Title>\n <BasicExample />\n </div>\n\n <div>\n <Typography.Title level={4}>带参数请求</Typography.Title>\n <WithParamsExample />\n </div>\n\n <div>\n <Typography.Title level={4}>成功与失败回调</Typography.Title>\n <CallbackExample />\n </div>\n\n <div>\n <Typography.Title level={4}>文件导出场景</Typography.Title>\n <ExportExample />\n </div>\n\n <div>\n <Typography.Title level={4}>表单提交场景</Typography.Title>\n <FormSubmitExample />\n </div>\n\n <div>\n <Typography.Title level={4}>刷新数据场景</Typography.Title>\n <RefreshExample />\n </div>\n\n <div>\n <Typography.Title level={4}>请求拦截</Typography.Title>\n <BeforeFetchExample />\n </div>\n </Flex>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ButtonGroup\",\n packageName: \"@kne/button-group\",\n importStatement: \"import * as _ButtonGroup from \\\"@kne/button-group\\\"\",\n component: component_36\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_37\n}]\n},{\n title: `ButtonFooter 底部按钮区`,\n description: `ButtonFooter 是页面底部按钮区域组件,在小屏幕下自动将内容渲染到 body,方便表单页面的操作按钮布局。`,\n code: `const { ButtonFooter } = _ButtonGroup;\nconst { Flex, Button, Space, Typography, Card, Form, Input } = antd;\nconst { useState } = React;\n\n// 基础用法\nconst BasicExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n ButtonFooter 固定在页面底部,在小屏幕(≤768px)下自动渲染到 body\n </Typography.Text>\n <Card\n title=\"页面内容区域\"\n style={{ width: 400, minHeight: 200 }}\n >\n <Typography.Paragraph>\n 这是页面的主要内容区域。ButtonFooter 会自动计算高度并设置 CSS 变量,\n 方便页面布局调整。\n </Typography.Paragraph>\n <Typography.Paragraph>\n 在移动端,按钮会自动固定在屏幕底部,确保操作按钮始终可见。\n </Typography.Paragraph>\n </Card>\n <ButtonFooter>\n <Flex justify=\"flex-end\" gap={8} style={{ padding: '16px 24px', background: '#fff', borderTop: '1px solid #f0f0f0' }}>\n <Button>取消</Button>\n <Button type=\"primary\">保存</Button>\n </Flex>\n </ButtonFooter>\n </Space>\n );\n};\n\n// 表单提交场景\nconst FormExample = () => {\n const [form] = Form.useForm();\n const [loading, setLoading] = useState(false);\n\n const handleSave = () => {\n setLoading(true);\n setTimeout(() => {\n setLoading(false);\n message.success('保存成功');\n }, 1000);\n };\n\n const handleSubmit = () => {\n setLoading(true);\n setTimeout(() => {\n setLoading(false);\n message.success('提交成功');\n }, 1000);\n };\n\n return (\n <Card title=\"表单底部操作\" style={{ width: 500 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 适用于表单页面的底部操作按钮\n </Typography.Text>\n <Form form={form} layout=\"vertical\">\n <Form.Item name=\"name\" label=\"名称\">\n <Input placeholder=\"请输入名称\" />\n </Form.Item>\n <Form.Item name=\"desc\" label=\"描述\">\n <Input.TextArea placeholder=\"请输入描述\" rows={4} />\n </Form.Item>\n </Form>\n <ButtonFooter>\n <Flex justify=\"flex-end\" gap={8} style={{ padding: '16px 0', borderTop: '1px solid #f0f0f0' }}>\n <Button onClick={() => form.resetFields()}>重置</Button>\n <Button onClick={handleSave}>保存草稿</Button>\n <Button type=\"primary\" loading={loading} onClick={handleSubmit}>\n 提交\n </Button>\n </Flex>\n </ButtonFooter>\n </Space>\n </Card>\n );\n};\n\n// 居中对齐\nconst CenterExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">按钮居中对齐</Typography.Text>\n <Card title=\"对话框\" style={{ width: 400 }}>\n <Typography.Paragraph>\n 这是对话框的内容区域,底部按钮居中对齐。\n </Typography.Paragraph>\n </Card>\n <ButtonFooter>\n <Flex justify=\"center\" gap={8} style={{ padding: '16px 24px', background: '#fff', borderTop: '1px solid #f0f0f0' }}>\n <Button>关闭</Button>\n <Button type=\"primary\">确认</Button>\n </Flex>\n </ButtonFooter>\n </Space>\n );\n};\n\n// 多按钮布局\nconst MultipleButtonsExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">多个操作按钮</Typography.Text>\n <Card title=\"详情页面\" style={{ width: 450 }}>\n <Typography.Paragraph>\n 页面详情内容区域...\n </Typography.Paragraph>\n <Typography.Paragraph>\n 支持多个按钮布局,包括主要操作、次要操作等。\n </Typography.Paragraph>\n </Card>\n <ButtonFooter>\n <Flex justify=\"space-between\" align=\"middle\" style={{ padding: '12px 24px', background: '#fff', borderTop: '1px solid #f0f0f0' }}>\n <Space>\n <Button type=\"text\" danger>删除</Button>\n <Button type=\"text\">导出</Button>\n </Space>\n <Space>\n <Button>编辑</Button>\n <Button type=\"primary\">提交审核</Button>\n </Space>\n </Flex>\n </ButtonFooter>\n </Space>\n );\n};\n\n// 紧凑样式\nconst CompactExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">紧凑样式</Typography.Text>\n <Card title=\"设置页面\" style={{ width: 400 }}>\n <Typography.Paragraph>\n 系统设置内容区域...\n </Typography.Paragraph>\n </Card>\n <ButtonFooter>\n <Flex justify=\"flex-end\" gap={8} style={{ padding: '8px 0', borderTop: '1px solid #f0f0f0' }}>\n <Button size=\"small\">取消</Button>\n <Button size=\"small\" type=\"primary\">保存设置</Button>\n </Flex>\n </ButtonFooter>\n </Space>\n );\n};\n\n// 禁用状态\nconst DisabledExample = () => {\n const [disabled, setDisabled] = useState(true);\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">按钮禁用状态</Typography.Text>\n <Space>\n <Button onClick={() => setDisabled(!disabled)} size=\"small\">\n {disabled ? '启用按钮' : '禁用按钮'}\n </Button>\n </Space>\n <Card title=\"详情页\" style={{ width: 400 }}>\n <Typography.Paragraph>\n 内容区域...\n </Typography.Paragraph>\n </Card>\n <ButtonFooter>\n <Flex justify=\"flex-end\" gap={8} style={{ padding: '16px 0', borderTop: '1px solid #f0f0f0' }}>\n <Button disabled={disabled}>编辑</Button>\n <Button type=\"primary\" disabled={disabled}>\n 提交\n </Button>\n </Flex>\n </ButtonFooter>\n </Space>\n );\n};\n\n// 步骤条场景\nconst StepsExample = () => {\n const [currentStep, setCurrentStep] = useState(0);\n const totalSteps = 3;\n\n const nextStep = () => {\n if (currentStep < totalSteps - 1) {\n setCurrentStep(currentStep + 1);\n }\n };\n\n const prevStep = () => {\n if (currentStep > 0) {\n setCurrentStep(currentStep - 1);\n }\n };\n\n const stepContent = [\n '第一步:填写基本信息',\n '第二步:上传相关文件',\n '第三步:确认提交信息'\n ];\n\n return (\n <Card title=\"步骤操作\" style={{ width: 450 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 当前步骤:{currentStep + 1} / {totalSteps}\n </Typography.Text>\n <div style={{ padding: '24px', background: '#f5f5f5', borderRadius: '8px', minHeight: '100px' }}>\n <Typography.Text>{stepContent[currentStep]}</Typography.Text>\n </div>\n <ButtonFooter>\n <Flex justify=\"space-between\" style={{ padding: '16px 0', borderTop: '1px solid #f0f0f0' }}>\n <Button disabled={currentStep === 0} onClick={prevStep}>\n 上一步\n </Button>\n <Button\n type=\"primary\"\n onClick={currentStep === totalSteps - 1 ? () => message.success('提交成功') : nextStep}\n >\n {currentStep === totalSteps - 1 ? '提交' : '下一步'}\n </Button>\n </Flex>\n </ButtonFooter>\n </Space>\n </Card>\n );\n};\n\n// 实际应用场景 - 完整页面\nconst FullPageExample = () => {\n const [form] = Form.useForm();\n\n const handleSubmit = () => {\n message.success('提交成功');\n };\n\n const handleSave = () => {\n message.success('已保存草稿');\n };\n\n return (\n <Card title=\"完整页面示例\" style={{ width: 500 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text type=\"secondary\">\n 模拟一个完整的表单页面,包含标题、内容区和底部操作按钮\n </Typography.Text>\n <div style={{ minHeight: '200px', padding: '20px', background: '#fafafa', borderRadius: '8px' }}>\n <Typography.Title level={5}>用户信息编辑</Typography.Title>\n <Form form={form} layout=\"vertical\">\n <Form.Item name=\"username\" label=\"用户名\">\n <Input placeholder=\"请输入用户名\" />\n </Form.Item>\n <Form.Item name=\"email\" label=\"邮箱\">\n <Input placeholder=\"请输入邮箱\" />\n </Form.Item>\n </Form>\n </div>\n <ButtonFooter>\n <Flex justify=\"flex-end\" gap={12} style={{ padding: '16px 24px', background: '#fff', borderTop: '1px solid #f0f0f0' }}>\n <Button onClick={() => form.resetFields()}>重置</Button>\n <Button onClick={handleSave}>保存草稿</Button>\n <Button type=\"primary\" onClick={handleSubmit}>提交</Button>\n </Flex>\n </ButtonFooter>\n </Space>\n </Card>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\">\n <Typography.Title level={3}>ButtonFooter 底部按钮区</Typography.Title>\n <Typography.Paragraph>\n ButtonFooter 是页面底部按钮区域组件,可以自动计算高度并设置 CSS 变量。\n 在小屏幕(≤768px)下,会将内容渲染到 body,确保按钮始终可见。\n 适用于表单页面、详情页面、对话框等场景。\n </Typography.Paragraph>\n\n <Flex vertical gap={32}>\n <div>\n <Typography.Title level={4}>基础用法</Typography.Title>\n <BasicExample />\n </div>\n\n <div>\n <Typography.Title level={4}>表单提交场景</Typography.Title>\n <FormExample />\n </div>\n\n <div>\n <Typography.Title level={4}>居中对齐</Typography.Title>\n <CenterExample />\n </div>\n\n <div>\n <Typography.Title level={4}>多按钮布局</Typography.Title>\n <MultipleButtonsExample />\n </div>\n\n <div>\n <Typography.Title level={4}>紧凑样式</Typography.Title>\n <CompactExample />\n </div>\n\n <div>\n <Typography.Title level={4}>禁用状态</Typography.Title>\n <DisabledExample />\n </div>\n\n <div>\n <Typography.Title level={4}>步骤操作</Typography.Title>\n <StepsExample />\n </div>\n\n <div>\n <Typography.Title level={4}>完整页面示例</Typography.Title>\n <FullPageExample />\n </div>\n </Flex>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ButtonGroup\",\n packageName: \"@kne/button-group\",\n importStatement: \"import * as _ButtonGroup from \\\"@kne/button-group\\\"\",\n component: component_36\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_37\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_1 from '@components/Common';\nimport * as component_2 from '@components/Modal';\nimport * as component_3 from 'antd';\nimport * as component_4 from '@kne/react-fetch';\nimport * as component_5 from 'lodash';\nconst readmeConfig = {\n name: `Common`,\n summary: `<p>为组件库提供通用的组件、方法、hooks</p>\n<h3>组件</h3>\n<ol>\n<li><strong>FetchButton</strong> - Button触发加载数据,支持弹窗展示加载结果</li>\n<li><strong>ScrollLoader</strong> - 下拉滚动加载组件,配合 Fetch 实现分页加载</li>\n<li><strong>SearchInput</strong> - 提供防抖的查询输入框</li>\n<li><strong>SimpleBarBox</strong> - 自定义滚动条容器(已废弃,请勿使用)</li>\n<li><strong>TreeField</strong> - 树形选择组件,支持单选和多选</li>\n<li><strong>CascaderField</strong> - 级联选择组件,支持多级联动选择</li>\n<li><strong>TypeDateRangePickerField</strong> - 类型日期范围选择器,支持按日、周、月选择</li>\n<li><strong>SuperSelectField</strong> - 新版高级选择组件,提供更强的自定义能力</li>\n<li><strong>SuperSelectUserField</strong> - 用户选择组件,展示用户头像和描述</li>\n<li><strong>SuperSelectTableListField</strong> - 表格列表选择组件</li>\n<li><strong>SuperSelectTreeField</strong> - 树形选择组件</li>\n<li><strong>AdvancedSelectField</strong> - 高级选择组件,支持用户选择、列表选择</li>\n<li><strong>UserField</strong> - 用户选择组件(旧版)</li>\n<li><strong>TableField</strong> - 表格选择组件</li>\n<li><strong>AddressSelectField</strong> - 地址选择组件</li>\n<li><strong>AddressInputField</strong> - 地址输入组件</li>\n<li><strong>AddressEnum</strong> - 地址枚举展示</li>\n<li><strong>FunctionSelectField</strong> - 职能选择组件</li>\n<li><strong>FunctionEnum</strong> - 职能枚举展示</li>\n<li><strong>IndustrySelectField</strong> - 行业选择组件</li>\n<li><strong>IndustryEnum</strong> - 行业枚举展示</li>\n</ol>\n<h3>方法</h3>\n<ol>\n<li><strong>changeMoneyToChinese</strong> - 将金额转化为大写的人民币金额</li>\n<li><strong>getPopupContainer</strong> - 获取弹窗容器</li>\n<li><strong>getContainerBody</strong> - 获取 body 容器</li>\n<li><strong>accept</strong> - 文件类型验证</li>\n<li><strong>createDeferred</strong> - 创建延迟对象</li>\n<li><strong>isNotEmpty</strong> - 非空判断</li>\n<li><strong>pxToNumber</strong> - px 转数字</li>\n<li><strong>numberToPx</strong> - 数字转 px</li>\n<li><strong>validateIDCard</strong> - 身份证号验证</li>\n</ol>\n<h3>HOC (高阶组件)</h3>\n<ol>\n<li><strong>withInputFile</strong> - 文件上传高阶组件</li>\n<li><strong>useFileUpload</strong> - 文件上传 Hook</li>\n<li><strong>InputFileButton</strong> - 文件上传按钮组件</li>\n<li><strong>InputFileLink</strong> - 文件上传链接组件</li>\n<li><strong>InputFileText</strong> - 文件上传文本组件</li>\n<li><strong>withOSSFile</strong> - OSS 文件上传高阶组件</li>\n</ol>\n<h3>Hooks</h3>\n<ol>\n<li><strong>useResize</strong> - 监听元素尺寸变化</li>\n<li><strong>usePreset</strong> - 获取预设配置</li>\n</ol>\n<h3>其他工具</h3>\n<ol>\n<li><strong>createTreeUtils</strong> - 创建树形数据工具函数</li>\n<li><strong>getScrollEl</strong> - 获取滚动元素</li>\n<li><strong>Scroller</strong> - 横向滚动组件</li>\n<li><strong>SelectInnerInput</strong> - 内部选择输入框基础组件</li>\n</ol>`,\n \n \n api: `<h2>FetchButton</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象,包含loader等接口方法</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>弹窗属性配置函数,接收 contextProps 参数</td>\n<td><code>(contextProps) => ModalProps</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalFunc</td>\n<td>弹窗功能函数,接收 modalApi 参数</td>\n<td><code>(modalApi) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onError</td>\n<td>错误处理函数</td>\n<td><code>(error) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>...ButtonProps</td>\n<td>继承 Button 组件所有属性</td>\n<td>-</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>ScrollLoader</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>isLoading</td>\n<td>是否正在加载</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>noMore</td>\n<td>是否已加载完毕</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>onLoader</td>\n<td>加载更多回调函数</td>\n<td><code>() => Promise<void></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>completeTips</td>\n<td>完成提示文本</td>\n<td><code>string</code></td>\n<td>\"没有更多了\"</td>\n</tr>\n<tr>\n<td>className</td>\n<td>样式类名</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子元素</td>\n<td><code>ReactNode</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>SearchInput</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>输入框值</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onSearch</td>\n<td>搜索回调函数,已防抖</td>\n<td><code>(value: string) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>debounce</td>\n<td>防抖延迟时间(毫秒)</td>\n<td><code>number</code></td>\n<td>500</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请输入\"</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否在弹窗中使用</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>...InputProps</td>\n<td>继承 Input.Search 组件所有属性</td>\n<td>-</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>TreeField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: Array<any>) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>fieldNames</td>\n<td>字段名称映射</td>\n<td><code>{ key, title, children }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大选择数量</td>\n<td><code>number</code></td>\n<td>MAX_VALUE</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否弹窗展示</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>checkStrictly</td>\n<td>父子节点是否不关联</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>searchPlaceholder</td>\n<td>搜索框占位符</td>\n<td><code>string</code></td>\n<td>\"搜索\"</td>\n</tr>\n</tbody>\n</table>\n<h2>CascaderField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: Array<any>) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大选择数量</td>\n<td><code>number</code></td>\n<td>MAX_VALUE</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否弹窗展示</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>overlayWidth</td>\n<td>弹窗宽度</td>\n<td><code>string</code></td>\n<td>\"460px\"</td>\n</tr>\n<tr>\n<td>menuItemWidth</td>\n<td>菜单项宽度</td>\n<td><code>string</code></td>\n<td>\"180px\"</td>\n</tr>\n<tr>\n<td>openLoadData</td>\n<td>是否开启懒加载</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>onlyAllowLastLevel</td>\n<td>是否只允许选择最后一级</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>parentIdKey</td>\n<td>父级ID字段名</td>\n<td><code>string</code></td>\n<td>\"id\"</td>\n</tr>\n<tr>\n<td>selectLevel</td>\n<td>选择层级</td>\n<td><code>number</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>searchPlaceholder</td>\n<td>搜索框占位符</td>\n<td><code>string</code></td>\n<td>\"搜索\"</td>\n</tr>\n<tr>\n<td>onSearch</td>\n<td>搜索回调函数</td>\n<td><code>(text: string, options) => Array</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>dataFormat</td>\n<td>数据格式化函数</td>\n<td><code>(data) => object</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>nodeFormat</td>\n<td>节点格式化函数</td>\n<td><code>(node) => object</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>TypeDateRangePickerField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>当前值,格式为 <code>{ type: string, value: [Date, Date] }</code></td>\n<td><code>object</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: object) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符数组</td>\n<td><code>[string, string]</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>...RangePickerProps</td>\n<td>继承 DatePicker.RangePicker 组件所有属性</td>\n<td>-</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>SuperSelectField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>getSearchProps</td>\n<td>获取搜索属性</td>\n<td><code>(text: string) => object</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>allowSelectedAll</td>\n<td>是否允许全选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否弹窗展示</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>showSelectedTag</td>\n<td>是否显示已选中标签</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>onConfirm</td>\n<td>确认回调</td>\n<td><code>(value) => void</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>SuperSelectUserField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择用户\"</td>\n</tr>\n<tr>\n<td>getSearchProps</td>\n<td>获取搜索属性</td>\n<td><code>(text: string) => object</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>allowSelectedAll</td>\n<td>是否允许全选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>labelKey</td>\n<td>标签字段名</td>\n<td><code>string</code></td>\n<td>\"label\"</td>\n</tr>\n<tr>\n<td>avatarKey</td>\n<td>头像字段名</td>\n<td><code>string</code></td>\n<td>\"avatar\"</td>\n</tr>\n<tr>\n<td>descriptionKey</td>\n<td>描述字段名</td>\n<td><code>string</code></td>\n<td>\"description\"</td>\n</tr>\n</tbody>\n</table>\n<h2>SuperSelectTableListField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>options</td>\n<td>选项数据数组</td>\n<td><code>Array<object></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>表格列配置</td>\n<td><code>Array<object></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>labelKey</td>\n<td>标签字段名</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>valueKey</td>\n<td>值字段名</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否弹窗展示</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>getSearchCallback</td>\n<td>搜索回调函数</td>\n<td><code>(searchProps, item, contextProps) => boolean</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>SuperSelectTreeField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>...TreeProps</td>\n<td>继承 Tree 组件所有属性</td>\n<td>-</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>AdvancedSelectField</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>当前选中的值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td><code>string</code></td>\n<td>\"请选择\"</td>\n</tr>\n<tr>\n<td>allowSelectAll</td>\n<td>是否允许全选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>showSelectedCount</td>\n<td>是否显示选中数量</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>countUnit</td>\n<td>数量单位</td>\n<td><code>string</code></td>\n<td>\"个\"</td>\n</tr>\n<tr>\n<td>allLabel</td>\n<td>全选项标签</td>\n<td><code>string</code></td>\n<td>\"全部\"</td>\n</tr>\n<tr>\n<td>showSelectedTag</td>\n<td>是否显示选中标签</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>getSearchProps</td>\n<td>获取搜索属性</td>\n<td><code>(text: string) => object</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>UserField (AdvancedSelect)</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>API配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultValue</td>\n<td>默认值</td>\n<td><code>Array<any></code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>变化回调</td>\n<td><code>(value: any) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>getSearchProps</td>\n<td>获取搜索属性</td>\n<td><code>(text: string) => object</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>allowSelectAll</td>\n<td>是否允许全选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>showSelectedCount</td>\n<td>是否显示选中数量</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>countUnit</td>\n<td>数量单位</td>\n<td><code>string</code></td>\n<td>\"人\"</td>\n</tr>\n<tr>\n<td>allLabel</td>\n<td>全选项标签</td>\n<td><code>string</code></td>\n<td>\"所有人\"</td>\n</tr>\n<tr>\n<td>showSelectedTag</td>\n<td>是否显示选中标签</td>\n<td><code>boolean</code></td>\n<td>true</td>\n</tr>\n</tbody>\n</table>\n<h2>AddressEnum</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>地址编码</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>FunctionEnum</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>职能编码</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>IndustryEnum</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>行业编码</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>InputFileButton / InputFileLink / InputFileText</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>accept</td>\n<td>接受的文件类型</td>\n<td><code>string</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>multiple</td>\n<td>是否多选</td>\n<td><code>boolean</code></td>\n<td>false</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>文件选择回调</td>\n<td><code>(file: File) => void</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>...TypographyProps</td>\n<td>继承 Typography 组件所有属性</td>\n<td>-</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h2>changeMoneyToChinese</h2>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>money</td>\n<td>金额数值</td>\n<td><code>number | string</code></td>\n</tr>\n</tbody>\n</table>\n<table>\n<thead>\n<tr>\n<th>返回值</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>chineseStr</td>\n<td>大写金额字符串</td>\n<td><code>string</code></td>\n</tr>\n</tbody>\n</table>\n<p>最大处理数字:999999999999999.999999</p>`,\n example: {\n isFull: false,\n className: `Common_d13bc`,\n style: `.Common_d13bc .scroll-list {\n max-height: 300px;\n}`,\n list: [{\n title: `FetchButton`,\n description: `Button触发加载数据,加载数据后在弹窗中展示`,\n code: `const {FetchButton} = _Common;\nconst {Typography, App} = _antd;\n\nconst {useModal} = _Modal;\n\nconst BaseExample = () => {\n const modal = useModal();\n\n return (<FetchButton\n api={{\n loader: () => {\n return [{id: 1, name: \"前端开发组\", count: 8, description: \"负责所有前端页面开发\"}, {\n id: 2,\n name: \"后端开发组\",\n count: 12,\n description: \"负责 API 和服务器开发\"\n }, {id: 3, name: \"测试组\", count: 5, description: \"负责功能测试和质量保证\"}, {\n id: 4,\n name: \"运维组\",\n count: 3,\n description: \"负责系统部署和维护\"\n },];\n },\n }}\n modalProps={(contextProps) => {\n const {data, fetchApi} = contextProps;\n return {\n title: \"团队信息\", children: (<div>\n <Typography.Paragraph>当前项目团队构成:</Typography.Paragraph>\n {data.map((item) => (<div key={item.id} style={{marginBottom: 16}}>\n <Typography.Text strong style={{fontSize: 15}}>\n {item.name}\n </Typography.Text>\n <div style={{marginTop: 4, color: '#666'}}>\n <Typography.Text>人数:{item.count} 人</Typography.Text>\n <Typography.Text style={{marginLeft: 16}}>\n 说明:{item.description}\n </Typography.Text>\n </div>\n </div>))}\n </div>),\n };\n }}\n modalFunc={modal}\n >\n 查看团队信息\n </FetchButton>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_2\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `Enum`,\n description: `枚举展示组件,展示地址、职能、行业等枚举信息`,\n code: `const Common = _Common;\nconst { Space } = _antd;\n\nconst { AddressEnum, FunctionEnum, IndustryEnum } = Common;\n\nconst BaseExample = () => {\n return (\n <Space direction={\"vertical\"}>\n <AddressEnum name={\"010\"} />\n <FunctionEnum name={\"010\"} />\n <IndustryEnum name={\"010\"} />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `ScrollLoader`,\n description: `下拉滚动加载组件,配合 Fetch 实现分页加载`,\n code: `const { get, merge, range } = lodash;\nconst { ScrollLoader } = _Common;\nconst { default: Fetch } = _reactFetch;\nconst { Card, List, Avatar, Typography, Space, Tag } = _antd;\n\nconst BaseExample = () => {\n const mockUsers = [\n { name: \"张三\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhang\", role: \"产品经理\" },\n { name: \"李四\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=li\", role: \"UI设计师\" },\n { name: \"王五\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=wang\", role: \"前端开发\" },\n { name: \"赵六\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhao\", role: \"后端开发\" },\n { name: \"孙七\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=sun\", role: \"测试工程师\" },\n { name: \"周八\", avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhou\", role: \"运维工程师\" },\n ];\n\n const mockComments = [\n \"这个功能很实用,期待上线!\",\n \"界面设计简洁美观,用户体验不错。\",\n \"建议增加批量操作功能。\",\n \"加载速度很快,性能很好。\",\n \"文档清晰,上手容易。\",\n ];\n\n return (\n <Card title=\"团队评论列表\" style={{ maxWidth: 600 }}>\n <Fetch\n loader={({ data }) => {\n const params = Object.assign(\n {\n perPage: 10,\n currentPage: 1,\n },\n data\n );\n return new Promise((resolve) => {\n const start = (params.currentPage - 1) * params.perPage;\n setTimeout(() => {\n resolve({\n totalCount: 50,\n pageData: range(start, start + params.perPage).map((key) => {\n const user = mockUsers[key % mockUsers.length];\n const comment = mockComments[key % mockComments.length];\n const hours = Math.floor(key / 3);\n return {\n id: key + 1,\n user: user.name,\n avatar: user.avatar,\n role: user.role,\n content: comment,\n time: \\`\\${hours}小时前\\`,\n likes: Math.floor(Math.random() * 50) + 1,\n };\n }),\n });\n }, 500);\n });\n }}\n render={(fetchApi) => {\n const pagination = {\n paramsType: \"data\",\n current: \"currentPage\",\n pageSize: \"perPage\",\n defaultPageSize: 10,\n };\n const current = get(\n fetchApi.requestParams,\n [pagination.paramsType, pagination.current],\n 1\n ),\n pageSize =\n get(fetchApi.requestParams, [\n pagination.paramsType,\n pagination.pageSize,\n ]) || pagination.defaultPageSize;\n\n const formatData = {\n list: fetchApi.data.pageData || [],\n total: fetchApi.data.totalCount || 0,\n };\n return (\n <ScrollLoader\n completeTips=\"\"\n className=\"scroll-list\"\n isLoading={!fetchApi.isComplete}\n noMore={!formatData.total || current * pageSize >= formatData.total}\n onLoader={async () => {\n await fetchApi.loadMore(\n merge({\n data: {\n [pagination.pageSize]: pageSize,\n [pagination.current]: current + 1,\n },\n }),\n (data, newData) => {\n return Object.assign({}, newData, {\n pageData: data.pageData.concat(newData.pageData),\n });\n }\n );\n }}\n >\n <List\n dataSource={formatData.list}\n renderItem={(item) => (\n <List.Item style={{ padding: \"12px 0\", borderBottom: \"1px solid #f0f0f0\" }}>\n <List.Item.Meta\n avatar={<Avatar src={item.avatar} />}\n title={\n <Space>\n <Typography.Text strong>{item.user}</Typography.Text>\n <Tag color=\"blue\" style={{ fontSize: 12 }}>{item.role}</Tag>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>{item.time}</Typography.Text>\n </Space>\n }\n description={\n <Space direction=\"vertical\" size={4}>\n <Typography.Text>{item.content}</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 👍 {item.likes} 人赞同\n </Typography.Text>\n </Space>\n }\n />\n </List.Item>\n )}\n />\n </ScrollLoader>\n );\n }}\n />\n </Card>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_4\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_5\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `SearchInput`,\n description: `提供防抖的查询输入框组件`,\n code: `const Common = _Common;\n\nconst { SearchInput } = Common;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [value, setValue] = useState(\"\");\n return (\n <SearchInput\n value={value}\n onSearch={(value) => {\n setValue(value);\n console.log(value);\n }}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n}]\n},{\n title: `AdvancedSelect`,\n description: `高级选择组件,支持用户选择、列表选择等功能`,\n code: `const { UserField } = _Common;\nconst { Space, Typography } = _antd;\n\nconst BaseExample = () => {\n const [value, setValue] = React.useState([]);\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text>\n 已选择 {value.length} 人\n </Typography.Text>\n <UserField\n value={value}\n onChange={setValue}\n getSearchProps={(text) => {\n return {\n data: { keyword: text },\n };\n }}\n allowSelectAll\n showSelectedCount\n countUnit=\"人\"\n allLabel=\"所有人\"\n placeholder=\"选择团队成员\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"张三\",\n value: 1,\n avatar: \"avatar-001\",\n description: \"前端工程师\",\n },\n {\n label: \"李四\",\n value: 2,\n avatar: \"avatar-002\",\n description: \"后端工程师\",\n },\n {\n label: \"王五\",\n value: 3,\n avatar: \"avatar-003\",\n description: \"产品经理\",\n },\n {\n label: \"赵六\",\n value: 4,\n avatar: \"avatar-004\",\n description: \"UI设计师\",\n },\n {\n label: \"钱七\",\n value: 5,\n avatar: \"avatar-005\",\n description: \"测试工程师\",\n },\n ],\n };\n },\n }}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `SuperSelect`,\n description: `新版高级选择组件,提供更强的自定义能力`,\n code: `const { SuperSelectField, SuperSelectTableListField, SuperSelectUserField } = _Common;\nconst { Space, Typography } = _antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [userValue, setUserValue] = useState([]);\n const [deptValue, setDeptValue] = useState([]);\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>用户选择</Typography.Text>\n <SuperSelectUserField\n value={userValue}\n onChange={setUserValue}\n allowSelectedAll\n placeholder=\"选择用户\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"张三\",\n value: 1,\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhang\" },\n description: \"高级前端工程师\",\n },\n {\n label: \"李四\",\n value: 2,\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=li\" },\n description: \"资深后端工程师\",\n },\n {\n label: \"王五\",\n value: 3,\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=wang\" },\n description: \"产品经理\",\n },\n {\n label: \"赵六\",\n value: 4,\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhao\" },\n description: \"UI设计师\",\n },\n {\n label: \"钱七\",\n value: 5,\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=qian\" },\n description: \"测试工程师\",\n },\n ],\n };\n },\n }}\n />\n\n <Typography.Text strong>部门选择</Typography.Text>\n <SuperSelectField\n isPopup={false}\n value={deptValue}\n onChange={setDeptValue}\n allowSelectedAll\n placeholder=\"选择部门\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"技术部\",\n value: \"tech\",\n description: \"负责产品技术实现\",\n },\n {\n label: \"产品部\",\n value: \"product\",\n description: \"负责产品规划和设计\",\n },\n {\n label: \"设计部\",\n value: \"design\",\n description: \"负责 UI/UX 设计\",\n },\n {\n label: \"市场部\",\n value: \"marketing\",\n description: \"负责市场推广和运营\",\n },\n ],\n };\n },\n }}\n />\n\n <Typography.Text strong>项目列表选择</Typography.Text>\n <SuperSelectTableListField\n isPopup={false}\n labelKey=\"name\"\n valueKey=\"id\"\n placeholder=\"选择项目\"\n getSearchCallback={(searchProps, item, contextProps) => {\n const { props } = contextProps;\n const { labelKey } = props;\n if (!searchProps.searchText) {\n return true;\n }\n return item[labelKey].indexOf(searchProps.searchText) > -1;\n }}\n options={[\n { id: 1, name: \"电商平台\", count: 15, description: \"在线购物平台\", disabled: false },\n { id: 2, name: \"OA系统\", count: 8, description: \"办公自动化系统\", disabled: true },\n { id: 3, name: \"CRM系统\", count: 10, description: \"客户关系管理\", disabled: false },\n { id: 4, name: \"数据大屏\", count: 5, description: \"数据可视化展示\", disabled: false },\n { id: 5, name: \"移动APP\", count: 12, description: \"移动端应用\", disabled: false },\n { id: 6, name: \"小程序\", count: 6, description: \"微信小程序\", disabled: false },\n ]}\n columns={[\n {\n name: \"name\",\n title: \"项目名称\",\n span: 8,\n },\n {\n name: \"count\",\n title: \"团队人数\",\n span: 8,\n },\n {\n name: \"description\",\n title: \"项目描述\",\n span: 8,\n },\n ]}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `TreeField`,\n description: `树形选择组件,支持单选和多选`,\n code: `const { TreeField } = _Common;\nconst { Space, Typography, Button } = _antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [value, setValue] = useState([]);\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>组织架构选择(多选)</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 已选择: {value.length} 个部门\n </Typography.Text>\n <TreeField\n api={{\n loader: () => {\n return [\n {\n key: 'tech',\n title: '技术部',\n children: [\n {\n key: 'frontend',\n title: '前端组',\n children: [\n { key: 'fe-web', title: 'Web前端' },\n { key: 'fe-mobile', title: '移动端' },\n ],\n },\n {\n key: 'backend',\n title: '后端组',\n children: [\n { key: 'be-java', title: 'Java后端' },\n { key: 'be-node', title: 'Node.js后端' },\n ],\n },\n ],\n },\n {\n key: 'product',\n title: '产品部',\n children: [\n { key: 'pm-web', title: 'Web产品' },\n { key: 'pm-mobile', title: '移动产品' },\n ],\n },\n {\n key: 'design',\n title: '设计部',\n children: [\n { key: 'ui', title: 'UI设计' },\n { key: 'ux', title: 'UX设计' },\n ],\n },\n {\n key: 'marketing',\n title: '市场部',\n children: [\n { key: 'market', title: '市场推广' },\n { key: 'operation', title: '运营' },\n ],\n },\n ];\n },\n }}\n value={value}\n onChange={setValue}\n placeholder=\"请选择部门\"\n single={false}\n />\n <Button onClick={() => setValue([])}>清空选择</Button>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `CascaderField`,\n description: `级联选择组件,支持多级联动选择`,\n code: `const { CascaderField } = _Common;\nconst { Space, Typography, Button } = _antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [value, setValue] = useState([]);\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>省市区级联选择(最多3个)</Typography.Text>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n 已选择: {value.length} 个区域\n </Typography.Text>\n <CascaderField\n api={{\n loader: () => {\n return [\n {\n id: 'zhejiang',\n label: '浙江省',\n children: [\n {\n id: 'hangzhou',\n label: '杭州市',\n children: [\n { id: 'xihu', label: '西湖区' },\n { id: 'gongshu', label: '拱墅区' },\n { id: 'jianggan', label: '江干区' },\n { id: 'binjiang', label: '滨江区' },\n ],\n },\n {\n id: 'ningbo',\n label: '宁波市',\n children: [\n { id: 'haishu', label: '海曙区' },\n { id: 'jiangbei', label: '江北区' },\n { id: 'yinzhou', label: '鄞州区' },\n ],\n },\n ],\n },\n {\n id: 'jiangsu',\n label: '江苏省',\n children: [\n {\n id: 'nanjing',\n label: '南京市',\n children: [\n { id: 'xuanwu', label: '玄武区' },\n { id: 'jianye', label: '建邺区' },\n { id: 'gulou', label: '鼓楼区' },\n ],\n },\n {\n id: 'suzhou',\n label: '苏州市',\n children: [\n { id: 'gusu', label: '姑苏区' },\n { id: 'wuzhong', label: '吴中区' },\n ],\n },\n ],\n },\n {\n id: 'guangdong',\n label: '广东省',\n children: [\n {\n id: 'guangzhou',\n label: '广州市',\n children: [\n { id: 'yuexiu', label: '越秀区' },\n { id: 'tianhe', label: '天河区' },\n { id: 'baiyun', label: '白云区' },\n ],\n },\n {\n id: 'shenzhen',\n label: '深圳市',\n children: [\n { id: 'futian', label: '福田区' },\n { id: 'nanshan', label: '南山区' },\n { id: 'baoan', label: '宝安区' },\n ],\n },\n ],\n },\n ];\n },\n }}\n value={value}\n onChange={setValue}\n placeholder=\"请选择省市区\"\n maxLength={3}\n isPopup={true}\n />\n <Button onClick={() => setValue([])}>清空选择</Button>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `TypeDateRangePicker`,\n description: `类型日期范围选择器,支持按日、周、月选择`,\n code: `const { TypeDateRangePickerField } = _Common;\nconst { Space, Typography } = _antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [value, setValue] = useState({\n type: 'date',\n value: [],\n });\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text>当前值: {JSON.stringify(value)}</Typography.Text>\n <TypeDateRangePickerField\n value={value}\n onChange={setValue}\n placeholder={['开始日期', '结束日期']}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `InputFile`,\n description: `文件上传组件,支持按钮、链接、文本等多种形式`,\n code: `const { InputFileButton, InputFileLink, InputFileText } = _Common;\nconst { Space, Typography, message, Alert } = _antd;\n\nconst BaseExample = () => {\n const handleFileChange = (file) => {\n console.log('选择的文件:', file);\n const sizeInMB = (file.size / 1024 / 1024).toFixed(2);\n message.success(\\`已选择文件: \\${file.name} (\\${sizeInMB}MB)\\`);\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>文件上传组件示例</Typography.Text>\n <Alert\n message=\"支持上传图片(JPG、PNG)和 PDF 文档,单个文件不超过 10MB\"\n type=\"info\"\n showIcon\n style={{ marginBottom: 16 }}\n />\n <Typography.Text>按钮形式上传:</Typography.Text>\n <InputFileButton\n accept=\".jpg,.png,.pdf\"\n onChange={handleFileChange}\n >\n 点击上传文件\n </InputFileButton>\n\n <Typography.Text style={{ marginTop: 8 }}>链接形式上传:</Typography.Text>\n <InputFileLink\n accept=\".jpg,.png,.pdf\"\n onChange={handleFileChange}\n >\n 选择要上传的文件\n </InputFileLink>\n\n <Typography.Text style={{ marginTop: 8 }}>文本形式上传:</Typography.Text>\n <InputFileText\n accept=\".jpg,.png,.pdf\"\n onChange={handleFileChange}\n >\n 浏览文件\n </InputFileText>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n},{\n title: `changeMoneyToChinese`,\n description: `金额转大写中文工具函数`,\n code: `const { changeMoneyToChinese } = _Common;\nconst { Space, Typography, Input, Button, Card } = _antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [amount, setAmount] = useState('');\n const chineseAmount = changeMoneyToChinese(amount);\n\n return (\n <Space direction=\"vertical\" style={{ width: '400px' }}>\n <Typography.Text strong style={{ fontSize: 16 }}>\n 金额转大写中文\n </Typography.Text>\n <Input\n placeholder=\"请输入金额\"\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n type=\"number\"\n prefix=\"¥\"\n size=\"large\"\n addonAfter=\"元\"\n />\n <Card size=\"small\" style={{ marginTop: 8 }}>\n <Typography.Text strong style={{ fontSize: 14 }}>\n 大写金额:\n </Typography.Text>\n <Typography.Text\n style={{\n fontSize: 18,\n fontWeight: 500,\n marginLeft: 8,\n color: '#1890ff'\n }}\n >\n {chineseAmount || '等待输入...'}\n </Typography.Text>\n </Card>\n <Space wrap>\n <Button onClick={() => setAmount('123456.78')}>\n 常用金额:123,456.78\n </Button>\n <Button onClick={() => setAmount('10000')}>\n 整数:10,000\n </Button>\n <Button onClick={() => setAmount('0')}>\n 零值:0\n </Button>\n <Button onClick={() => setAmount('')}>\n 清空\n </Button>\n </Space>\n <Typography.Text type=\"secondary\" style={{ fontSize: 12 }}>\n * 最大支持金额:999,999,999,999,999.999999\n </Typography.Text>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Common\",\n packageName: \"@components/Common\",\n component: component_1\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_3\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_26 from '@components/Drawer';\nimport * as component_27 from '@components/Global';\nimport * as component_28 from 'antd';\nimport * as component_29 from 'lodash';\nimport * as component_30 from '@components/FormInfo';\nconst readmeConfig = {\n name: `Drawer`,\n summary: `<p>屏幕边缘滑出的浮层面板,适用于展示详细信息、表单编辑、数据查看等场景。支持三种使用方式:受控组件、Hook 调用、按钮触发。</p>\n<p>核心特性包括:</p>\n<ul>\n<li><strong>灵活的打开方式</strong>:支持受控模式、函数调用和按钮触发三种方式</li>\n<li><strong>多种尺寸规格</strong>:提供 small(600px)、default(1000px)、large(全屏-64px)三种预设尺寸</li>\n<li><strong>丰富的自定义能力</strong>:支持自定义底部按钮、装饰器修饰、异步操作等</li>\n<li><strong>数据加载集成</strong>:DrawerButton 组件结合数据加载,自动在加载完成后打开抽屉</li>\n<li><strong>优雅的交互体验</strong>:内置滚动条美化、加载状态支持、异步操作反馈</li>\n</ul>\n<p>适用于用户详情查看、表单编辑、信息展示、操作确认等多种业务场景。</p>`,\n \n \n api: `<h3>Drawer</h3>\n<p>屏幕边缘滑出的浮层面板,用于展示详细信息、表单编辑等场景。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>抽屉标题</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>size</td>\n<td>抽屉尺寸,可选值:<code>small</code>(600px)、<code>default</code>(1000px)、<code>large</code>(calc(100vw-64px))</td>\n<td>string</td>\n<td><code>small</code></td>\n</tr>\n<tr>\n<td>children</td>\n<td>抽屉内容,可以是 JSX 或函数,函数时可接收 close 方法和 props</td>\n<td>ReactNode | function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footer</td>\n<td>抽屉底部内容,设为 null 且 footerButtons 未设置时不显示底部,函数时可接收 close 方法和 props</td>\n<td>ReactNode | function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>底部按钮配置数组,默认显示\"取消\"和\"确定\"按钮</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onConfirm</td>\n<td>点击确认按钮触发的回调,返回 Promise 时按钮显示 loading 状态,返回 false 时不关闭抽屉</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onCancel</td>\n<td>点击取消按钮触发的回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClose</td>\n<td>抽屉关闭时的回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>closable</td>\n<td>是否显示关闭按钮</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>maskClosable</td>\n<td>点击蒙层是否允许关闭</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>disabledScroller</td>\n<td>是否禁用滚动条美化</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>抽屉内容修饰器,可在内容外层添加装饰</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>open</td>\n<td>受控模式下抽屉的显示状态</td>\n<td>boolean</td>\n<td>-</td>\n</tr>\n<tr>\n<td>width</td>\n<td>自定义抽屉宽度</td>\n<td>string | number</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:其他未列出的属性可参考 Ant Design Drawer 组件</p>\n<h4>footerButtons 数组项说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>按钮文字</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>type</td>\n<td>按钮类型,参考 Ant Design Button</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>danger</td>\n<td>是否为危险按钮</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>ButtonComponent</td>\n<td>自定义按钮组件</td>\n<td>Component</td>\n<td>LoadingButton</td>\n</tr>\n<tr>\n<td>onClick</td>\n<td>点击事件回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>autoClose</td>\n<td>点击后是否自动关闭抽屉</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>display</td>\n<td>是否显示该按钮</td>\n<td>boolean | function</td>\n<td>true</td>\n</tr>\n</tbody>\n</table>\n<h3>useDrawer</h3>\n<p>用于获取一个可以调用 Drawer 的 Hook 函数,配合 AppDrawer 使用。</p>\n<h4>返回值</h4>\n<p>返回一个数组:<code>[drawer, DrawerContextHolder]</code></p>\n<ul>\n<li>\n<p><strong>drawer</strong>: 函数,执行后可打开一个 Drawer,参数同 Drawer 组件属性</p>\n<ul>\n<li>返回对象包含 <code>destroy</code> 方法用于关闭 Drawer</li>\n<li>返回对象包含 <code>update</code> 方法用于更新 Drawer 配置</li>\n</ul>\n</li>\n<li>\n<p><strong>DrawerContextHolder</strong>: 必须渲染在组件树中,用于承载 Drawer 实例</p>\n</li>\n</ul>\n<h3>DrawerButton</h3>\n<p>结合 FetchButton 功能的按钮组件,点击后加载数据,加载完成后自动打开 Drawer。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>FetchButton 的 API 配置对象</td>\n<td><code>{ loader: Function }</code></td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>Drawer 属性配置,可以是对象或函数</td>\n<td>object | function({ data, fetchApi, close })</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onError</td>\n<td>数据加载错误回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:其他属性同 Ant Design Button 组件</p>\n<h4>modalProps 为函数时的参数说明</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>data</td>\n<td>加载的数据</td>\n<td>any</td>\n</tr>\n<tr>\n<td>fetchApi</td>\n<td>Fetch API 对象</td>\n<td>object</td>\n</tr>\n<tr>\n<td>close</td>\n<td>关闭 Drawer 的方法</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>AppDrawer</h3>\n<p>全局 Drawer 提供者组件,为内部使用 useDrawer 的组件提供上下文环境。</p>\n<h4>使用方式</h4>\n<p>在应用最外层包裹 AppDrawer,即可在任意组件中使用 useDrawer:</p>\n<pre><code class=\"language-javascript\">import { AppDrawer } from '@components/Drawer';\n\nfunction App() {\n return (\n <AppDrawer>\n <YourAppContent />\n </AppDrawer>\n );\n}\n</code></pre>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础用法`,\n description: `展示 Drawer 组件的三种使用方式:受控组件、Hook调用、按钮触发`,\n code: `const { default: Drawer, useDrawer, DrawerButton } = _Drawer;\nconst { Button, Space, Typography, Descriptions, Avatar, Tag } = _antd;\nconst { useState } = React;\nconst {PureGlobal} = _Global;\n\nconst BasicExample = () => {\n const [open, setOpen] = useState(false);\n const drawer = useDrawer();\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>方式一:受控组件</Typography.Text>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开详情抽屉\n </Button>\n <Drawer\n title=\"用户信息\"\n open={open}\n onClose={() => setOpen(false)}\n width={600}\n >\n <Descriptions column={1} bordered>\n <Descriptions.Item label=\"姓名\">张三</Descriptions.Item>\n <Descriptions.Item label=\"部门\">技术部</Descriptions.Item>\n <Descriptions.Item label=\"职位\">高级前端工程师</Descriptions.Item>\n <Descriptions.Item label=\"邮箱\">zhangsan@example.com</Descriptions.Item>\n </Descriptions>\n </Drawer>\n\n <Typography.Text strong>方式二:Hook调用</Typography.Text>\n <Button\n onClick={() => {\n drawer({\n title: \"项目信息\",\n children: (\n <div>\n <Typography.Paragraph>项目名称:电商平台</Typography.Paragraph>\n <Typography.Paragraph>项目负责人:李四</Typography.Paragraph>\n <Typography.Paragraph>开发周期:6个月</Typography.Paragraph>\n <Typography.Paragraph>团队成员:12人</Typography.Paragraph>\n </div>\n ),\n });\n }}\n >\n 使用Hook打开\n </Button>\n </Space>\n );\n};\n\nrender(<PureGlobal><BasicExample /></PureGlobal>);\n\n`,\n scope: [{\n name: \"_Drawer\",\n packageName: \"@components/Drawer\",\n component: component_26\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_27\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_28\n}]\n},{\n title: `用户详情`,\n description: `使用 DrawerButton 加载数据后展示用户详细信息,模拟真实业务场景`,\n code: `const { DrawerButton } = _Drawer;\nconst { Card, Avatar, Typography, Tag, Space, Divider, Descriptions, Timeline } = _antd;\nconst { range } = lodash;\nconst {PureGlobal} = _Global;\n\nconst UserDetailExample = () => {\n const mockUserData = {\n id: 1,\n name: \"张三\",\n avatar: { src: \"https://api.dicebear.com/7.x/avataaars/svg?seed=zhang\" },\n role: \"高级前端工程师\",\n department: \"技术部-前端组\",\n email: \"zhangsan@company.com\",\n phone: \"138****8888\",\n joinDate: \"2020-03-15\",\n skills: [\"React\", \"Vue\", \"TypeScript\", \"Node.js\"],\n projects: [\n { name: \"电商平台重构\", role: \"负责人\", status: \"进行中\", date: \"2024-01\" },\n { name: \"OA系统开发\", role: \"核心开发\", status: \"已完成\", date: \"2023-08\" },\n { name: \"数据大屏\", role: \"参与\", status: \"已完成\", date: \"2023-03\" },\n ],\n performance: [\n { quarter: \"2024 Q1\", score: 95, comment: \"工作表现优异,项目交付及时\" },\n { quarter: \"2023 Q4\", score: 92, comment: \"技术能力强,团队协作好\" },\n { quarter: \"2023 Q3\", score: 88, comment: \"稳步提升,建议加强文档能力\" },\n ],\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <DrawerButton\n type=\"primary\"\n api={{\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(mockUserData);\n }, 800);\n });\n },\n }}\n modalProps={(contextProps) => {\n const { data } = contextProps;\n return {\n title: \"员工档案详情\",\n size: \"large\",\n children: (\n <div>\n <Card style={{ marginBottom: 16 }}>\n <Space align=\"start\" size=\"large\">\n <Avatar size={80} src={data.avatar.src} />\n <Space direction=\"vertical\" size={4}>\n <Typography.Title level={4} style={{ margin: 0 }}>\n {data.name}\n </Typography.Title>\n <Space>\n <Tag color=\"blue\">{data.role}</Tag>\n <Tag color=\"green\">{data.department}</Tag>\n </Space>\n <Typography.Text type=\"secondary\">\n 入职时间:{data.joinDate}\n </Typography.Text>\n </Space>\n </Space>\n </Card>\n\n <Descriptions title=\"基本信息\" column={2} bordered style={{ marginBottom: 16 }}>\n <Descriptions.Item label=\"工号\">EMP{String(data.id).padStart(4, '0')}</Descriptions.Item>\n <Descriptions.Item label=\"姓名\">{data.name}</Descriptions.Item>\n <Descriptions.Item label=\"部门\">{data.department}</Descriptions.Item>\n <Descriptions.Item label=\"职位\">{data.role}</Descriptions.Item>\n <Descriptions.Item label=\"邮箱\">{data.email}</Descriptions.Item>\n <Descriptions.Item label=\"电话\">{data.phone}</Descriptions.Item>\n </Descriptions>\n\n <Typography.Title level={5}>技术栈</Typography.Title>\n <Space wrap style={{ marginBottom: 16 }}>\n {data.skills.map((skill) => (\n <Tag key={skill} color=\"processing\">{skill}</Tag>\n ))}\n </Space>\n\n <Typography.Title level={5}>项目经历</Typography.Title>\n <Card size=\"small\" style={{ marginBottom: 16 }}>\n {data.projects.map((project, index) => (\n <div key={index}>\n <Space>\n <Typography.Text strong>{project.name}</Typography.Text>\n <Tag color={project.status === \"进行中\" ? \"processing\" : \"success\"}>\n {project.status}\n </Tag>\n </Space>\n <Typography.Text type=\"secondary\" style={{ marginLeft: 16 }}>\n {project.role} · {project.date}\n </Typography.Text>\n {index < data.projects.length - 1 && <Divider style={{ margin: \"8px 0\" }} />}\n </div>\n ))}\n </Card>\n\n <Typography.Title level={5}>绩效考核</Typography.Title>\n <Timeline\n items={data.performance.map((item) => ({\n children: (\n <Space direction=\"vertical\" size={2}>\n <Space>\n <Typography.Text strong>{item.quarter}</Typography.Text>\n <Tag color={item.score >= 90 ? \"success\" : \"warning\"}>\n {item.score}分\n </Tag>\n </Space>\n <Typography.Text type=\"secondary\">{item.comment}</Typography.Text>\n </Space>\n ),\n }))}\n />\n </div>\n ),\n };\n }}\n >\n 查看员工档案\n </DrawerButton>\n </Space>\n );\n};\n\nrender(<PureGlobal><UserDetailExample /></PureGlobal>);\n\n`,\n scope: [{\n name: \"_Drawer\",\n packageName: \"@components/Drawer\",\n component: component_26\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_27\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_28\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_29\n}]\n},{\n title: `表单编辑`,\n description: `在 Drawer 中展示表单进行编辑,支持确认和取消操作`,\n code: `const {useFormDrawer, FormDrawerButton, default: FormInfo} = _FormInfo;\nconst {Button, Space, Typography, message, Divider} = _antd;\nconst {PureGlobal} = _Global;\n\nconst FormDrawerExample = () => {\n const formDrawer = useFormDrawer();\n const {Form} = FormInfo;\n const {Input} = FormInfo.fields;\n\n const handleEdit = (userData) => {\n formDrawer({\n title: \"编辑员工信息\", size: \"small\", formProps: {\n data: userData, onSubmit: async (data) => {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n message.success(\\`已更新员工信息:\\${data.name}\\`);\n }\n }, children: (<FormInfo\n column={1}\n list={[<Input\n name=\"name\"\n label=\"姓名\"\n rule=\"REQ\"\n tips=\"请输入员工姓名\"\n />, <Input\n name=\"department\"\n label=\"部门\"\n rule=\"REQ\"\n options={[{label: \"技术部\", value: \"tech\"}, {\n label: \"产品部\",\n value: \"product\"\n }, {label: \"设计部\", value: \"design\"}, {label: \"市场部\", value: \"marketing\"}]}\n single\n tips=\"请选择所属部门\"\n />, <Input\n name=\"position\"\n label=\"职位\"\n rule=\"REQ\"\n tips=\"请输入职位名称\"\n />, <Input\n name=\"email\"\n label=\"邮箱\"\n rule=\"REQ EMAIL\"\n tips=\"请输入有效的邮箱地址\"\n />, <Input\n name=\"phone\"\n label=\"电话\"\n rule=\"REQ TEL\"\n tips=\"请输入有效的手机号码\"\n />]}\n />)\n });\n };\n\n return (<Space direction=\"vertical\" style={{width: '100%'}}>\n <Typography.Text strong>使用 useFormDrawer 编辑员工信息</Typography.Text>\n <Typography.Text type=\"secondary\" style={{fontSize: 12}}>\n FormDrawer 结合了 Drawer 和 FormInfo 的功能,提供了更便捷的表单抽屉体验,支持校验规则和自动数据加载\n </Typography.Text>\n\n <Divider/>\n\n <Button\n type=\"primary\"\n onClick={() => {\n handleEdit({\n name: \"张三\",\n department: \"tech\",\n position: \"高级前端工程师\",\n email: \"zhangsan@example.com\",\n phone: \"13888888888\",\n });\n }}\n >\n 编辑员工信息\n </Button>\n <Button\n onClick={() => {\n handleEdit({\n name: \"李四\",\n department: \"product\",\n position: \"产品经理\",\n email: \"lisi@example.com\",\n phone: \"13999999999\",\n });\n }}\n >\n 编辑另一位员工\n </Button>\n </Space>);\n};\n\nrender(<PureGlobal><FormDrawerExample/></PureGlobal>);\n\n`,\n scope: [{\n name: \"_Drawer\",\n packageName: \"@components/Drawer\",\n component: component_26\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_30\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_27\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_28\n}]\n},{\n title: `不同尺寸`,\n description: `展示 small、default、large 三种不同尺寸的 Drawer`,\n code: `const { useDrawer } = _Drawer;\nconst { Button, Space, Typography, Descriptions, Timeline, Card } = _antd;\nconst {PureGlobal} = _Global;\n\nconst SizesExample = () => {\n const drawer = useDrawer();\n\n const content1 = (\n <Descriptions column={1} bordered>\n <Descriptions.Item label=\"项目名称\">OA系统</Descriptions.Item>\n <Descriptions.Item label=\"负责人\">张三</Descriptions.Item>\n <Descriptions.Item label=\"开始时间\">2024-01-01</Descriptions.Item>\n <Descriptions.Item label=\"状态\">进行中</Descriptions.Item>\n <Descriptions.Item label=\"进度\">60%</Descriptions.Item>\n </Descriptions>\n );\n\n const content2 = (\n <div>\n <Typography.Paragraph>\n <strong>项目概述:</strong>\n 这是一个企业办公自动化系统,提供包括审批流程、日程管理、文档协作等功能。\n </Typography.Paragraph>\n <Descriptions column={2} bordered style={{ marginTop: 16 }}>\n <Descriptions.Item label=\"项目经理\">李四</Descriptions.Item>\n <Descriptions.Item label=\"技术负责人\">王五</Descriptions.Item>\n <Descriptions.Item label=\"开发周期\">6个月</Descriptions.Item>\n <Descriptions.Item label=\"团队规模\">12人</Descriptions.Item>\n <Descriptions.Item label=\"预算\">50万</Descriptions.Item>\n <Descriptions.Item label=\"截止时间\">2024-06-30</Descriptions.Item>\n </Descriptions>\n <Typography.Title level={5} style={{ marginTop: 24 }}>\n 项目里程碑\n </Typography.Title>\n <Timeline\n items={[\n {\n children: \"需求分析与设计完成\",\n color: \"green\",\n },\n {\n children: \"前端框架搭建完成\",\n color: \"green\",\n },\n {\n children: \"后端接口开发进行中\",\n color: \"blue\",\n },\n {\n children: \"系统联调测试\",\n color: \"gray\",\n },\n {\n children: \"上线部署\",\n color: \"gray\",\n },\n ]}\n />\n </div>\n );\n\n const content3 = (\n <div>\n <Card title=\"项目基本信息\" style={{ marginBottom: 16 }}>\n <Descriptions column={3} bordered>\n <Descriptions.Item label=\"项目名称\">电商平台重构</Descriptions.Item>\n <Descriptions.Item label=\"项目编号\">PRJ-2024-001</Descriptions.Item>\n <Descriptions.Item label=\"项目类型\">重构升级</Descriptions.Item>\n <Descriptions.Item label=\"负责人\">赵六</Descriptions.Item>\n <Descriptions.Item label=\"开发团队\">技术部</Descriptions.Item>\n <Descriptions.Item label=\"优先级\">P0</Descriptions.Item>\n </Descriptions>\n </Card>\n\n <Card title=\"团队成员\" style={{ marginBottom: 16 }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n {[\n { name: \"张三\", role: \"技术负责人\", count: 8 },\n { name: \"李四\", role: \"前端组长\", count: 12 },\n { name: \"王五\", role: \"后端组长\", count: 15 },\n { name: \"赵六\", role: \"测试负责人\", count: 6 },\n { name: \"钱七\", role: \"UI设计师\", count: 3 },\n ].map((member) => (\n <div key={member.name} style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0', borderBottom: '1px solid #f0f0f0' }}>\n <span><strong>{member.name}</strong> - {member.role}</span>\n <span>{member.count} 人</span>\n </div>\n ))}\n </Space>\n </Card>\n\n <Card title=\"技术架构\">\n <Space wrap>\n {[\"React\", \"TypeScript\", \"Next.js\", \"Node.js\", \"PostgreSQL\", \"Redis\", \"Docker\", \"Kubernetes\"].map((tech) => (\n <span key={tech} style={{ padding: '4px 12px', background: '#e6f7ff', borderRadius: '4px', color: '#1890ff' }}>\n {tech}\n </span>\n ))}\n </Space>\n </Card>\n\n <Card title=\"开发计划\" style={{ marginTop: 16 }}>\n <Timeline\n items={[\n {\n children: <><strong>第一阶段(1-2月):</strong>技术调研与架构设计</>,\n color: \"green\",\n },\n {\n children: <><strong>第二阶段(3-4月):</strong>核心功能开发</>,\n color: \"green\",\n },\n {\n children: <><strong>第三阶段(5月):</strong>联调测试与优化</>,\n color: \"blue\",\n },\n {\n children: <><strong>第四阶段(6月):</strong>灰度发布与上线</>,\n color: \"gray\",\n },\n ]}\n />\n </Card>\n </div>\n );\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>选择不同尺寸的抽屉</Typography.Text>\n <Button\n onClick={() => {\n drawer({\n title: \"Small 尺寸\",\n size: \"small\",\n children: content1,\n });\n }}\n >\n Small (600px)\n </Button>\n <Button\n onClick={() => {\n drawer({\n title: \"Default 尺寸\",\n size: \"default\",\n children: content2,\n });\n }}\n >\n Default (1000px)\n </Button>\n <Button\n onClick={() => {\n drawer({\n title: \"Large 尺寸\",\n size: \"large\",\n children: content3,\n });\n }}\n >\n Large (全屏-64px)\n </Button>\n </Space>\n );\n};\n\nrender(<PureGlobal><SizesExample /></PureGlobal>);\n\n`,\n scope: [{\n name: \"_Drawer\",\n packageName: \"@components/Drawer\",\n component: component_26\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_27\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_28\n}]\n},{\n title: `自定义操作`,\n description: `自定义底部按钮、添加额外功能按钮,支持异步操作`,\n code: `const { useDrawer, DrawerButton } = _Drawer;\nconst { Button, Space, Typography, message, Popconfirm, Tag, Descriptions } = _antd;\nconst {PureGlobal} = _Global;\n\nconst CustomActionsExample = () => {\n const drawer = useDrawer();\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Typography.Text strong>自定义底部按钮和额外操作</Typography.Text>\n\n <Button\n onClick={() => {\n drawer({\n title: \"自定义按钮\",\n size: \"small\",\n children: (\n <div>\n <Typography.Paragraph>这个示例展示了如何自定义底部按钮。</Typography.Paragraph>\n <Typography.Paragraph>自定义了三个按钮:预览、取消、保存。</Typography.Paragraph>\n </div>\n ),\n footerButtons: [\n {\n children: \"预览\",\n onClick: () => {\n message.info(\"预览功能\");\n },\n },\n {\n children: \"取消\",\n onClick: () => {\n message.info(\"已取消\");\n },\n },\n {\n type: \"primary\",\n children: \"保存\",\n onClick: async () => {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n message.success(\"保存成功!\");\n return true;\n },\n },\n ],\n });\n }}\n >\n 自定义按钮示例\n </Button>\n\n <DrawerButton\n api={{\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n id: 1,\n name: \"张三\",\n role: \"高级前端工程师\",\n department: \"技术部\",\n status: \"在职\",\n joinDate: \"2020-03-15\",\n });\n }, 500);\n });\n },\n }}\n modalProps={(contextProps) => {\n const { data } = contextProps;\n return {\n title: \"员工档案操作\",\n size: \"small\",\n children: (\n <Descriptions column={1} bordered>\n <Descriptions.Item label=\"姓名\">{data.name}</Descriptions.Item>\n <Descriptions.Item label=\"职位\">{data.role}</Descriptions.Item>\n <Descriptions.Item label=\"部门\">{data.department}</Descriptions.Item>\n <Descriptions.Item label=\"状态\">\n <Tag color=\"green\">{data.status}</Tag>\n </Descriptions.Item>\n <Descriptions.Item label=\"入职时间\">{data.joinDate}</Descriptions.Item>\n </Descriptions>\n ),\n footerButtons: [\n {\n children: \"查看详情\",\n onClick: () => {\n message.info(\"查看更多详情\");\n },\n },\n {\n children: \"导出档案\",\n onClick: () => {\n message.info(\"正在导出档案...\");\n },\n },\n {\n children: \"编辑\",\n type: \"default\",\n onClick: () => {\n message.info(\"打开编辑模式\");\n },\n },\n {\n type: \"primary\",\n children: \"确认\",\n onClick: async () => {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n message.success(\"操作成功!\");\n return true;\n },\n },\n ],\n };\n }}\n >\n 加载数据并自定义操作\n </DrawerButton>\n\n <Button\n danger\n onClick={() => {\n drawer({\n title: \"删除确认\",\n size: \"small\",\n children: (\n <div>\n <Typography.Paragraph>\n <Typography.Text type=\"warning\">⚠️ 警告:</Typography.Text>\n 此操作将永久删除该员工档案,删除后无法恢复。\n </Typography.Paragraph>\n <Typography.Paragraph>是否继续删除?</Typography.Paragraph>\n </div>\n ),\n footerButtons: [\n {\n children: \"取消\",\n onClick: () => {\n message.info(\"已取消删除\");\n },\n },\n {\n danger: true,\n type: \"primary\",\n children: \"确认删除\",\n onClick: async () => {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n message.success(\"已删除员工档案\");\n return true;\n },\n },\n ],\n });\n }}\n >\n 危险操作示例\n </Button>\n </Space>\n );\n};\n\nrender(<PureGlobal><CustomActionsExample /></PureGlobal>);\n\n`,\n scope: [{\n name: \"_Drawer\",\n packageName: \"@components/Drawer\",\n component: component_26\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_27\n},{\n name: \"_antd\",\n packageName: \"antd\",\n component: component_28\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_33 from '@kne/react-enum';\nimport * as component_34 from 'antd';\nimport * as component_35 from '@kne/remote-loader';\nconst readmeConfig = {\n name: `react-enum`,\n summary: `<p>枚举值管理和展示组件,用于统一管理应用中的枚举数据,如性别、状态、类型等选项列表。</p>\n<h2>何时使用</h2>\n<ul>\n<li>需要展示枚举值的描述文本时</li>\n<li>需要将枚举列表渲染为下拉框、单选框等表单组件时</li>\n<li>需要统一管理应用中的枚举数据时</li>\n<li>需要支持多语言的枚举描述时</li>\n</ul>\n<h2>特性</h2>\n<ul>\n<li>📦 统一的枚举数据管理</li>\n<li>🔄 支持同步/异步加载</li>\n<li>📡 内置LRU缓存机制</li>\n<li>🌍 支持多语言</li>\n<li>🎨 多种格式化方式</li>\n<li>🔧 灵活的渲染函数</li>\n</ul>`,\n \n \n api: `<h2>Enum 组件 API</h2>\n<h3>Enum(默认导出)</h3>\n<p>用于获取单个或多个枚举值的展示内容。</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>moduleName</td>\n<td>枚举模块名称,对应预设中配置的枚举名称</td>\n<td>string | string[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>枚举值,当提供时获取单个枚举项;不提供时获取整个枚举列表</td>\n<td>string | number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>format</td>\n<td>格式化方式:'default'返回描述文本,'origin'返回原始对象,'option'返回{label, value}格式</td>\n<td>'default' | 'origin' | 'option'</td>\n<td>'default'</td>\n</tr>\n<tr>\n<td>force</td>\n<td>是否强制刷新缓存,跳过缓存直接请求</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子元素或渲染函数。函数接收(data, fetchApi)参数</td>\n<td>ReactNode | Function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>数据加载中时的占位内容</td>\n<td>ReactNode</td>\n<td>'--'</td>\n</tr>\n<tr>\n<td>error</td>\n<td>加载失败时的展示内容</td>\n<td>ReactNode | Function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>loading</td>\n<td>自定义加载中状态的展示</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>EnumResource</h3>\n<p>用于获取完整的枚举列表资源。</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>moduleName</td>\n<td>枚举模块名称,支持数组以同时获取多个枚举</td>\n<td>string | string[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>format</td>\n<td>格式化方式</td>\n<td>'origin' | 'option' | 'default'</td>\n<td>'origin'</td>\n</tr>\n<tr>\n<td>children</td>\n<td>渲染函数,接收枚举列表作为参数</td>\n<td>Function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>数据加载中时的占位内容</td>\n<td>ReactNode</td>\n<td>'--'</td>\n</tr>\n<tr>\n<td>error</td>\n<td>加载失败时的展示内容</td>\n<td>ReactNode | Function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>loading</td>\n<td>自定义加载中状态的展示</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>枚举配置</h3>\n<p>枚举数据通过 <code>preset</code> 函数或 <code>PureGlobal/Global</code> 组件的 <code>preset.enums</code> 配置:</p>\n<pre><code class=\"language-javascript\">// 全局配置\npreset({\n base: {\n gender: () => [\n { value: 'M', description: '男' },\n { value: 'F', description: '女' }\n ]\n }\n});\n\n// 或通过 Global 组件配置\n<PureGlobal preset={{\n enums: {\n status: async ({ language }) => {\n // 支持异步加载\n return [\n { value: '1', description: '启用' },\n { value: '0', description: '禁用' }\n ];\n }\n }\n}}>\n</code></pre>\n<h3>枚举项数据结构</h3>\n<table>\n<thead>\n<tr>\n<th>字段名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>枚举值</td>\n<td>string | number</td>\n<td>是</td>\n</tr>\n<tr>\n<td>description</td>\n<td>枚举描述文本</td>\n<td>string</td>\n<td>是</td>\n</tr>\n<tr>\n<td>translation</td>\n<td>多语言翻译对象</td>\n<td>object</td>\n<td>否</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `EnumLegacy`,\n description: `兼容老版本Enum的API`,\n code: `const { default: Enum, preset } = _ReactEnum;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { Divider } = antd;\n\npreset({\n base: {\n confirm: () => [{ description: '是', value: 'Y' }, {\n description: '否', value: 'N'\n }]\n }\n});\n\nconst BaseExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n return <PureGlobal preset={{\n enums: {\n gender: [{ value: 'M', description: '男' }, {\n value: 'F', description: '女'\n }], marital: async () => [{ description: '已婚', value: 'Y' }, {\n description: '未婚', value: 'N'\n }]\n }\n }}>\n <Enum moduleName=\"gender\" name=\"M\" />\n <Divider />\n <Enum moduleName=\"gender\">{(data) => {\n return data.map((data) => \\`\\${data.value}:\\${data.description}\\`).join(',');\n }}</Enum>\n <Divider />\n <Enum moduleName={['gender', 'marital']}>{([gender, marital]) => {\n return <div>\n <div>{gender.map((data) => \\`\\${data.value}:\\${data.description}\\`).join(',')}</div>\n <div>{marital.map((data) => \\`\\${data.value}:\\${data.description}\\`).join(',')}</div>\n </div>;\n }}</Enum>\n <Divider />\n <Enum moduleName=\"confirm\" name=\"Y\" />\n <Enum moduleName=\"confirm\" name=\"N\">{(data) => data.description}</Enum>\n </PureGlobal>;\n});\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_ReactEnum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n},{\n title: `基础用法`,\n description: `展示枚举的基本使用,包括获取单个枚举值和枚举列表`,\n code: `const { default: Enum } = _Enum;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { Space, Select, Divider } = antd;\nconst BaseExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n // 同步加载的枚举\n gender: [\n { value: \"M\", description: \"男\" },\n { value: \"F\", description: \"女\" },\n ],\n // 异步加载的枚举\n status: async ({ locale }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n { value: \"1\", description: \"启用\" },\n { value: \"0\", description: \"禁用\" },\n ]);\n }, 500);\n });\n },\n },\n }}\n >\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <h4>获取单个枚举值</h4>\n <Space>\n <span>性别:</span>\n <Enum moduleName=\"gender\" name=\"M\" />\n <Divider type=\"vertical\" />\n <span>自定义渲染:</span>\n <Enum moduleName=\"gender\" name=\"F\">\n {(data) => <strong style={{ color: \"#f5222d\" }}>{data.description}</strong>}\n </Enum>\n </Space>\n </div>\n \n <div>\n <h4>获取枚举列表</h4>\n <Enum moduleName=\"gender\">\n {(list) => {\n return (\n <Space>\n <span>可选项:</span>\n {list.map((item, index) => (\n <span key={item.value}>\n {item.description}\n {index < list.length - 1 && \"、\"}\n </span>\n ))}\n </Space>\n );\n }}\n </Enum>\n </div>\n \n <div>\n <h4>渲染为下拉框</h4>\n <Enum moduleName=\"status\">\n {(list) => {\n return (\n <Select\n style={{ width: 150 }}\n placeholder=\"请选择状态\"\n options={list.map((item) => ({\n value: item.value,\n label: item.description,\n }))}\n />\n );\n }}\n </Enum>\n </div>\n \n <div>\n <h4>占位符和加载状态</h4>\n <Space>\n <span>状态:</span>\n <Enum \n moduleName=\"status\" \n name=\"1\"\n placeholder=\"加载中...\"\n />\n </Space>\n </div>\n \n <div>\n <h4>使用format=\"option\"直接获取选项格式</h4>\n <Enum moduleName=\"gender\" format=\"option\">\n {(list) => (\n <Select\n style={{ width: 150 }}\n placeholder=\"请选择性别\"\n options={list}\n />\n )}\n </Enum>\n </div>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<BaseExample />);\n`,\n scope: [{\n name: \"_Enum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n},{\n title: `异步加载与缓存`,\n description: `展示异步加载枚举数据、Loading状态和强制刷新缓存`,\n code: `const { default: Enum } = _Enum;\nconst { Space, Button, message } = antd;\nconst { useState } = React;\nconst { createWithRemoteLoader } = remoteLoader;\n\nconst AsyncEnumExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n const [refreshKey, setRefreshKey] = useState(0);\n \n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n // 异步加载枚举数据\n userStatus: async ({ language }) => {\n // 模拟从服务器获取数据\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n { value: \"active\", description: \"活跃\" },\n { value: \"inactive\", description: \"非活跃\" },\n { value: \"pending\", description: \"待审核\" },\n { value: \"banned\", description: \"已禁用\" },\n ]);\n }, 1500);\n });\n },\n // 同步枚举数据\n priority: [\n { value: \"low\", description: \"低优先级\" },\n { value: \"medium\", description: \"中优先级\" },\n { value: \"high\", description: \"高优先级\" },\n { value: \"urgent\", description: \"紧急\" },\n ],\n },\n }}\n >\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <h4>异步加载枚举(带Loading状态)</h4>\n <Enum \n key={refreshKey}\n moduleName=\"userStatus\" \n name=\"active\"\n loading={<span>正在加载用户状态...</span>}\n placeholder=\"--\"\n >\n {(data) => <div>当前状态:{data.description}</div>}\n </Enum>\n </div>\n \n <div>\n <h4>强制刷新缓存</h4>\n <Space>\n <Enum \n moduleName=\"userStatus\" \n name=\"banned\"\n force={refreshKey > 0}\n >\n {(data) => data.description}\n </Enum>\n <Button \n onClick={() => {\n setRefreshKey(prev => prev + 1);\n message.info(\"已刷新缓存\");\n }}\n >\n 刷新缓存\n </Button>\n </Space>\n </div>\n \n <div>\n <h4>同步枚举数据(立即显示)</h4>\n <Space>\n <Enum moduleName=\"priority\" name=\"high\" />\n <Enum moduleName=\"priority\" name=\"urgent\">\n {(data) => <span style={{ color: \"red\" }}>{data.description}</span>}\n </Enum>\n </Space>\n </div>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<AsyncEnumExample />);\n\n`,\n scope: [{\n name: \"_Enum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n},{\n title: `格式化方式`,\n description: `展示不同的格式化方式和自定义渲染`,\n code: `const { default: Enum } = _Enum;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { Space, Divider, Card } = antd;\n\nconst FormatEnumExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n orderStatus: [\n { value: \"created\", description: \"已创建\", color: \"#666\" },\n { value: \"paid\", description: \"已支付\", color: \"#1890ff\" },\n { value: \"shipped\", description: \"已发货\", color: \"#52c41a\" },\n { value: \"completed\", description: \"已完成\", color: \"#52c41a\" },\n { value: \"cancelled\", description: \"已取消\", color: \"#f5222d\" },\n ],\n },\n }}\n >\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <Card title=\"不同格式化方式\" size=\"small\">\n <Space direction=\"vertical\">\n <div>\n <strong>默认格式(format=\"default\"):</strong>\n <Enum moduleName=\"orderStatus\" name=\"paid\" format=\"default\" />\n </div>\n \n <Divider />\n \n <div>\n <strong>原始对象(format=\"origin\"):</strong>\n <Enum moduleName=\"orderStatus\" name=\"paid\" format=\"origin\">\n {(data) => (\n <pre>{JSON.stringify(data, null, 2)}</pre>\n )}\n </Enum>\n </div>\n \n <Divider />\n \n <div>\n <strong>选项格式(format=\"option\"):</strong>\n <Enum moduleName=\"orderStatus\" name=\"paid\" format=\"option\">\n {(data) => {\n return (\n <span>label: {data.description}, value: {data.value}</span>\n )\n }}\n </Enum>\n </div>\n </Space>\n </Card>\n \n <Card title=\"自定义渲染\" size=\"small\">\n <Space>\n <Enum moduleName=\"orderStatus\" name=\"shipped\" format=\"origin\">\n {(data) => (\n <span style={{ color: data.color }}>\n ● {data.description}\n </span>\n )}\n </Enum>\n \n <Enum moduleName=\"orderStatus\" name=\"cancelled\" format=\"origin\">\n {(data) => (\n <span style={{ \n padding: \"2px 8px\",\n backgroundColor: data.color,\n color: \"#fff\",\n borderRadius: \"4px\"\n }}>\n {data.description}\n </span>\n )}\n </Enum>\n </Space>\n </Card>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<FormatEnumExample />);\n\n`,\n scope: [{\n name: \"_Enum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n},{\n title: `渲染枚举列表`,\n description: `将枚举列表渲染为各种表单组件`,\n code: `const { default: Enum } = _Enum;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { Space, Select, Radio, Checkbox, Table } = antd;\n\nconst ListEnumExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n department: [\n { value: \"tech\", description: \"技术部\" },\n { value: \"product\", description: \"产品部\" },\n { value: \"design\", description: \"设计部\" },\n { value: \"marketing\", description: \"市场部\" },\n { value: \"hr\", description: \"人力资源部\" },\n { value: \"finance\", description: \"财务部\" },\n ],\n role: [\n { value: \"admin\", description: \"管理员\", level: 1 },\n { value: \"manager\", description: \"经理\", level: 2 },\n { value: \"employee\", description: \"员工\", level: 3 },\n { value: \"intern\", description: \"实习生\", level: 4 },\n ],\n },\n }}\n >\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <h4>渲染为 Select 下拉框</h4>\n <Enum moduleName=\"department\">\n {(list) => (\n <Select\n style={{ width: 200 }}\n placeholder=\"请选择部门\"\n options={list.map((item) => ({\n value: item.value,\n label: item.description,\n }))}\n />\n )}\n </Enum>\n </div>\n \n <div>\n <h4>渲染为 Radio 单选组</h4>\n <Enum moduleName=\"role\">\n {(list) => (\n <Radio.Group>\n {list.map((item) => (\n <Radio key={item.value} value={item.value}>\n {item.description}\n </Radio>\n ))}\n </Radio.Group>\n )}\n </Enum>\n </div>\n \n <div>\n <h4>渲染为 Checkbox 多选组</h4>\n <Enum moduleName=\"department\">\n {(list) => (\n <Checkbox.Group>\n {list.slice(0, 4).map((item) => (\n <Checkbox key={item.value} value={item.value}>\n {item.description}\n </Checkbox>\n ))}\n </Checkbox.Group>\n )}\n </Enum>\n </div>\n \n <div>\n <h4>渲染为 Table 表格</h4>\n <Enum moduleName=\"role\" format=\"origin\">\n {(list) => (\n <Table\n size=\"small\"\n pagination={false}\n columns={[\n { title: \"编码\", dataIndex: \"value\", key: \"value\" },\n { title: \"名称\", dataIndex: \"description\", key: \"description\" },\n { title: \"级别\", dataIndex: \"level\", key: \"level\" },\n ]}\n dataSource={list.map(item => ({ ...item, key: item.value }))}\n />\n )}\n </Enum>\n </div>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<ListEnumExample />);\n\n`,\n scope: [{\n name: \"_Enum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n},{\n title: `多枚举模块`,\n description: `同时获取多个枚举模块和错误处理`,\n code: `const { default: Enum } = _Enum;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { Space, Card, Tag } = antd;\n\nconst MultiEnumExample = createWithRemoteLoader({\n modules: ['components-core:Global@PureGlobal']\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n country: [\n { value: \"CN\", description: \"中国\" },\n { value: \"US\", description: \"美国\" },\n { value: \"UK\", description: \"英国\" },\n { value: \"JP\", description: \"日本\" },\n ],\n language: [\n { value: \"zh-CN\", description: \"简体中文\" },\n { value: \"en-US\", description: \"英语\" },\n { value: \"ja-JP\", description: \"日语\" },\n { value: \"ko-KR\", description: \"韩语\" },\n ],\n timezone: [\n { value: \"UTC+8\", description: \"北京时间\" },\n { value: \"UTC+0\", description: \"格林威治时间\" },\n { value: \"UTC-5\", description: \"纽约时间\" },\n { value: \"UTC+9\", description: \"东京时间\" },\n ],\n },\n }}\n >\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <Card title=\"同时获取多个枚举模块\" size=\"small\">\n <Enum moduleName={[\"country\", \"language\", \"timezone\"]}>\n {([countries, languages, timezones]) => (\n <Space direction=\"vertical\">\n <div>\n <strong>国家列表:</strong>\n <Space>\n {countries.map(item => (\n <Tag key={item.value}>{item.description}</Tag>\n ))}\n </Space>\n </div>\n <div>\n <strong>语言列表:</strong>\n <Space>\n {languages.map(item => (\n <Tag key={item.value} color=\"blue\">{item.description}</Tag>\n ))}\n </Space>\n </div>\n <div>\n <strong>时区列表:</strong>\n <Space>\n {timezones.map(item => (\n <Tag key={item.value} color=\"green\">{item.description}</Tag>\n ))}\n </Space>\n </div>\n </Space>\n )}\n </Enum>\n </Card>\n \n <Card title=\"组合使用多个枚举\" size=\"small\">\n <Space>\n <span>用户来自</span>\n <Enum moduleName=\"country\" name=\"CN\">\n {(data) => <strong>{data.description}</strong>}\n </Enum>\n <span>,使用</span>\n <Enum moduleName=\"language\" name=\"zh-CN\">\n {(data) => <strong>{data.description}</strong>}\n </Enum>\n <span>,时区为</span>\n <Enum moduleName=\"timezone\" name=\"UTC+8\">\n {(data) => <strong>{data.description}</strong>}\n </Enum>\n </Space>\n </Card>\n \n <Card title=\"错误处理\" size=\"small\">\n <Space direction=\"vertical\">\n <div>\n <strong>不存在的枚举模块:</strong>\n <Enum \n moduleName=\"notExist\" \n name=\"test\"\n error={<span style={{ color: \"red\" }}>枚举加载失败</span>}\n />\n </div>\n <div>\n <strong>不存在的枚举值(显示占位符):</strong>\n <Enum \n moduleName=\"country\" \n name=\"XX\"\n placeholder=\"未知国家\"\n />\n </div>\n </Space>\n </Card>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<MultiEnumExample />);\n\n`,\n scope: [{\n name: \"_Enum\",\n packageName: \"@kne/react-enum\",\n importStatement: \"import * as _ReactEnum from \\\"@kne/react-enum\\\"\",\n component: component_33\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_34\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_35\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_6 from '@components/Features';\nimport * as component_7 from '@components/Global';\nimport * as component_8 from '@components/Layout';\nimport * as component_9 from 'react-router-dom';\nimport * as component_10 from 'antd';\nconst readmeConfig = {\n name: `Features`,\n summary: `<p>Features 是一个功能开关管理组件,用于在系统中通过条件控制功能的开启或关闭,实现系统功能的灵活配置。</p>\n<p>通过全局配置的方式,Features 组件可以统一管理系统功能的可见性和可访问性,避免在代码中散落大量判断逻辑。它支持基于依赖关系的智能判断,只有当功能及其依赖项都满足条件时才会被标记为可用状态。同时,该组件还支持为功能的开启和关闭状态传递不同的配置参数,实现更精细的交互控制。</p>\n<p>核心特性:</p>\n<ul>\n<li><strong>集中配置管理</strong>:通过 Global preset 统一声明,避免判断语句散落在代码各处</li>\n<li><strong>依赖关系支持</strong>:智能判断功能是否可用,只有满足所有依赖条件才开启</li>\n<li><strong>双状态参数</strong>:可为开启和关闭状态分别配置不同的参数(options/rejectedOptions)</li>\n<li><strong>调试模式</strong>:提供 debug 模式方便开发时查看功能状态和真实 ID</li>\n<li><strong>嵌套功能管理</strong>:支持 system/module/feature 三级结构,通过冒号连接完整 ID</li>\n</ul>\n<p>适用于企业级管理系统、SaaS 平台、多租户应用等需要精细化功能控制的场景。</p>`,\n \n \n api: `<h3>Features 组件</h3>\n<p>Features 是一个功能开关组件,用于根据配置控制子组件的显示或隐藏。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>功能标识符,对应 preset.features.profile 中定义的 id</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子内容,可以是 JSX 或函数。为函数时接收 {isPass, options, currentId} 参数</td>\n<td>ReactNode | Function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>children 函数参数</h4>\n<p>当 children 为函数时,接收的参数对象包含以下属性:</p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>isPass</td>\n<td>功能是否通过(开启)</td>\n<td>boolean</td>\n</tr>\n<tr>\n<td>options</td>\n<td>开启或关闭状态对应的配置参数</td>\n<td>any</td>\n</tr>\n<tr>\n<td>currentId</td>\n<td>当前功能的完整 ID(包含父级路径)</td>\n<td>string</td>\n</tr>\n</tbody>\n</table>\n<h3>features 配置</h3>\n<p>features 配置在 Global preset 中定义。</p>\n<h4>features 配置属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>debug</td>\n<td>是否开启调试模式,开启后会在控制台打印所有功能的 ID 和判断状态</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>profile</td>\n<td>功能配置树结构</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>profile 配置结构</h3>\n<p>profile 采用树形结构配置系统的功能模块。</p>\n<h4>profile 节点属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>当前节点的标识符,同级节点中需唯一,完整 ID 由父级 ID 和当前 ID 通过冒号连接</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>type</td>\n<td>节点类型,可选值为:system(系统根节点)、module(功能模块)、feature(具体功能)</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>节点中文名称,仅用于标识和说明</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>close</td>\n<td>是否强制关闭该功能。true 表示关闭,false 或不配置表示开启(存在该节点配置时)</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>dependencies</td>\n<td>依赖的功能列表,数组中的 ID 必须是完整的功能 ID。只有所有依赖功能都开启时,当前功能才会被标记为开启</td>\n<td>array<string></td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>options</td>\n<td>功能开启时传递给 children 的参数</td>\n<td>any</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rejectedOptions</td>\n<td>功能关闭时传递给 children 的参数</td>\n<td>any</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子功能节点数组</td>\n<td>array<object></td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>功能判断规则</h4>\n<ol>\n<li>功能开启条件:profile 中存在该节点配置,且 close 不为 true,且所有 dependencies 依赖的功能都已开启</li>\n<li>功能关闭条件:profile 中不存在该节点配置,或 close 为 true,或存在依赖项功能关闭</li>\n<li>根节点 type 必须为 system</li>\n</ol>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `基础用法 - 依赖关系控制功能开关`,\n description: `展示如何通过依赖关系控制功能模块的开启与关闭,批量导入功能依赖编辑模块`,\n code: `const { default: Features } = _Features;\nconst { default: Layout, PermissionsPage } = layout;\nconst { PureGlobal } = global;\n\nconst BaseExample = () => {\n return (\n <PureGlobal\n preset={{\n features: {\n debug: true,\n profile: {\n id: \"hr-system\",\n type: \"system\",\n name: \"人力资源管理系统\",\n children: [\n {\n id: \"employee\",\n type: \"module\",\n name: \"员工管理\",\n children: [\n {\n id: \"import\",\n type: \"feature\",\n name: \"批量导入\",\n dependencies: [\"hr-system:employee:edit\"],\n },\n {\n id: \"export\",\n type: \"feature\",\n name: \"数据导出\",\n },\n ],\n },\n {\n id: \"attendance\",\n type: \"module\",\n name: \"考勤管理\",\n children: [\n {\n id: \"check-in\",\n type: \"feature\",\n name: \"签到打卡\",\n },\n ],\n },\n {\n id: \"edit\",\n type: \"module\",\n name: \"编辑模块\",\n },\n ],\n },\n },\n }}\n >\n <Layout navigation={{ isFixed: false }}>\n <PermissionsPage name=\"employee\" openFeatures>\n <Features id=\"import\">\n <div>\n <h3>批量导入员工数据</h3>\n <p>支持 Excel 文件批量导入,一次性添加多名员工</p>\n </div>\n </Features>\n <Features id=\"export\">\n <div>\n <h3>导出员工数据</h3>\n <p>导出员工列表到 Excel,支持自定义筛选条件</p>\n </div>\n </Features>\n <Features id=\"analytics\">\n <div>\n <h3>数据分析</h3>\n <p>统计分析员工数据,生成可视化报表</p>\n </div>\n </Features>\n </PermissionsPage>\n </Layout>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Features\",\n packageName: \"@components/Features\",\n component: component_6\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_7\n},{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_8\n}]\n},{\n title: `页面级功能控制`,\n description: `展示如何在多页面应用中使用 Features 控制不同页面的功能模块,销售趋势图、客户增长图等功能展示`,\n code: `const {default: Features} = _Features;\nconst {default: Layout, PermissionsPage} = layout;\nconst {PureGlobal} = global;\nconst {Route, Routes} = Router;\n\nconst ModuleExample = () => {\n return (<PureGlobal\n preset={{\n features: {\n debug: true, profile: {\n id: \"crm-system\", type: \"system\", name: \"客户关系管理系统\", children: [{\n id: \"dashboard\", type: \"module\", name: \"数据看板\", children: [{\n id: \"sales-chart\", type: \"feature\", name: \"销售趋势图\",\n }, {\n id: \"customer-chart\", type: \"feature\", name: \"客户增长图\",\n },],\n }, {\n id: \"customer\", type: \"module\", name: \"客户管理\", children: [{\n id: \"advanced-filter\",\n type: \"feature\",\n name: \"高级筛选\",\n dependencies: [\"crm-system:dashboard\"],\n },],\n },],\n },\n },\n }}\n >\n <Layout\n navigation={{\n isFixed: false, showIndex: false, base: '/Features', list: [{\n key: \"dashboard\", title: \"数据看板\", path: \"/Features\",\n }, {\n key: \"customer\", title: \"客户管理\", path: \"/Features/customer\",\n },],\n }}\n >\n <Routes>\n <Route\n path=\"/Features\"\n element={<PermissionsPage name=\"dashboard\" openFeatures>\n <div>\n <h2>数据看板</h2>\n <div style={{\n padding: '16px',\n marginBottom: '16px',\n border: '1px solid #d9d9d9',\n borderRadius: '4px'\n }}>\n <Features id=\"sales-chart\">\n <h3>销售趋势分析</h3>\n <p>展示最近30天销售数据变化趋势</p>\n </Features>\n </div>\n <div style={{padding: '16px', border: '1px solid #d9d9d9', borderRadius: '4px'}}>\n <Features id=\"customer-chart\">\n <h3>客户增长分析</h3>\n <p>展示客户数量变化趋势</p>\n </Features>\n </div>\n </div>\n </PermissionsPage>}\n />\n <Route\n path=\"/Features/customer\"\n element={<PermissionsPage name=\"customer\" openFeatures>\n <div>\n <h2>客户管理</h2>\n <div style={{padding: '16px', border: '1px solid #d9d9d9', borderRadius: '4px'}}>\n <Features id=\"advanced-filter\">\n <h3>高级筛选功能</h3>\n <p>支持多维度组合筛选客户数据</p>\n </Features>\n </div>\n </div>\n </PermissionsPage>}\n />\n </Routes>\n </Layout>\n </PureGlobal>);\n};\n\nrender(<ModuleExample/>);\n\n`,\n scope: [{\n name: \"_Features\",\n packageName: \"@components/Features\",\n component: component_6\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_7\n},{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_8\n},{\n name: \"Router\",\n packageName: \"react-router-dom\",\n component: component_9\n}]\n},{\n title: `动态参数传递`,\n description: `展示如何根据功能开启/关闭状态传递不同的配置参数(options/rejectedOptions),薪资可见性和绩效考核功能`,\n code: `const { default: Features } = _Features;\nconst { default: Layout, PermissionsPage } = layout;\nconst { PureGlobal } = global;\nconst { useState } = React;\nconst { Button, Space, Card, Tag, Alert } = antd;\n\nconst OptionsExample = () => {\n const [featureEnabled, setFeatureEnabled] = useState(true);\n\n return (\n <PureGlobal\n preset={{\n features: {\n debug: true,\n profile: {\n id: \"hr-system\",\n type: \"system\",\n name: \"人力资源系统\",\n children: [\n {\n id: \"employee\",\n type: \"module\",\n name: \"员工管理\",\n children: [\n {\n id: \"salary-visibility\",\n type: \"feature\",\n name: \"薪资可见性\",\n options: {\n permission: \"full\",\n canEdit: true,\n maxViewLevel: \"all\"\n },\n rejectedOptions: {\n permission: \"limited\",\n canEdit: false,\n maxViewLevel: \"self\"\n },\n close: !featureEnabled,\n },\n {\n id: \"performance\",\n type: \"feature\",\n name: \"绩效考核\",\n options: {\n scoreRange: \"0-100\",\n hasReview: true,\n allowAppeal: true\n },\n rejectedOptions: {\n scoreRange: \"0-10\",\n hasReview: false,\n allowAppeal: false\n }\n }\n ],\n },\n ],\n },\n },\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card>\n <Button\n type=\"primary\"\n onClick={() => {\n setFeatureEnabled((value) => !value);\n }}\n >\n {featureEnabled ? \"关闭薪资功能\" : \"开启薪资功能\"}\n </Button>\n <p style={{ marginTop: 12 }}>\n 点击按钮切换薪资可见性功能,观察不同状态下传递的参数变化\n </p>\n </Card>\n\n <Layout navigation={{ isFixed: false }}>\n <PermissionsPage name=\"employee\" openFeatures>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"薪资可见性功能\" size=\"small\">\n <Features id=\"salary-visibility\">\n {({ isPass, options }) => (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message={isPass ? \"功能已开启\" : \"功能已关闭\"}\n type={isPass ? \"success\" : \"warning\"}\n showIcon\n />\n <div>\n <strong>权限级别:</strong>\n <Tag color={isPass ? \"green\" : \"orange\"}>\n {options.permission}\n </Tag>\n </div>\n <div>\n <strong>编辑权限:</strong>\n <Tag color={options.canEdit ? \"blue\" : \"default\"}>\n {options.canEdit ? \"允许编辑\" : \"只读\"}\n </Tag>\n </div>\n <div>\n <strong>查看范围:</strong>\n <Tag>{options.maxViewLevel}</Tag>\n </div>\n </Space>\n )}\n </Features>\n </Card>\n\n <Card title=\"绩效考核功能\" size=\"small\">\n <Features id=\"performance\">\n {({ isPass, options }) => (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message={isPass ? \"功能已开启\" : \"功能已关闭\"}\n type=\"success\"\n showIcon\n />\n <div>\n <strong>评分范围:</strong>\n <Tag>{options.scoreRange}</Tag>\n </div>\n <div>\n <strong>绩效复核:</strong>\n <Tag color={options.hasReview ? \"blue\" : \"default\"}>\n {options.hasReview ? \"启用\" : \"禁用\"}\n </Tag>\n </div>\n <div>\n <strong>申诉功能:</strong>\n <Tag color={options.allowAppeal ? \"blue\" : \"default\"}>\n {options.allowAppeal ? \"允许\" : \"禁止\"}\n </Tag>\n </div>\n </Space>\n )}\n </Features>\n </Card>\n </Space>\n </PermissionsPage>\n </Layout>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<OptionsExample />);\n\n`,\n scope: [{\n name: \"_Features\",\n packageName: \"@components/Features\",\n component: component_6\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_7\n},{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_8\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_10\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_11 from '@components/File';\nimport * as component_12 from '@components/Global';\nimport * as component_13 from '@kne/remote-loader';\nimport * as component_14 from 'antd';\nconst readmeConfig = {\n name: `File`,\n summary: `<p>File 组件提供了一套完整的文件管理解决方案,包括文件展示、OSS 文件 ID 转换、文件列表展示、文件下载等功能。</p>\n<p>该组件集成了文件上传、预览、编辑、删除等常见操作,支持通过 OSS ID 自动获取文件访问地址,并提供文件列表组件来展示和管理多个文件。同时提供了文件下载、文件预览链接等便捷组件,方便在各种场景下使用。</p>\n<p>核心特性:</p>\n<ul>\n<li><strong>自动 OSS 地址转换</strong>:支持通过文件 ID 自动获取 OSS 访问地址,无需手动处理 URL 转换</li>\n<li><strong>完整的文件操作</strong>:提供文件预览、编辑名称、下载、删除等完整操作功能</li>\n<li><strong>灵活的列表展示</strong>:支持自定义列渲染、权限控制、上传状态展示</li>\n<li><strong>多种使用方式</strong>:提供按钮、链接、列表等多种形式的组件,适应不同场景需求</li>\n<li><strong>下载状态管理</strong>:内置下载状态管理,支持下载进度控制和回调处理</li>\n</ul>\n<p>适用于文档管理系统、文件共享平台、数据导入导出等需要文件处理的应用场景。</p>`,\n \n \n api: `<h3>File 组件</h3>\n<p>File 组件用于通过 OSS ID 获取文件访问地址并展示文件内容。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的访问地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>渲染函数,接收 <code>{ url }</code> 参数</td>\n<td>Function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>error</td>\n<td>加载失败时显示的内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>null</td>\n</tr>\n<tr>\n<td>loading</td>\n<td>加载中显示的内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>null</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>\n<h3>Download 组件</h3>\n<p>文件下载按钮组件,支持通过 OSS ID 或 URL 下载文件。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的下载地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>下载后的文件名</td>\n<td>string</td>\n<td>否</td>\n<td>未命名下载文件</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onSuccess</td>\n<td>下载成功回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onError</td>\n<td>下载失败回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>\n<h3>List 组件</h3>\n<p>文件列表展示组件,支持文件预览、编辑名称、下载、删除等操作。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>文件数据列表</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>getPermission</td>\n<td>权限控制函数,接收 <code>{ type, itemData }</code> 参数,返回 <code>false</code> 表示无权限</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>hasPreview</td>\n<td>是否启用预览功能</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>infoItemRenders</td>\n<td>自定义列配置,数组中每项包含 <code>span</code>(栅格数)和 <code>render</code>(渲染函数)</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>renderModal</td>\n<td>自定义 Modal 渲染函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>操作 API 配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onEdit</td>\n<td>编辑文件名称回调,接收参数 <code>(formData, itemData)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onPreview</td>\n<td>预览文件回调,接收参数 <code>(itemData)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onDelete</td>\n<td>删除文件回调,接收参数 <code>(itemData)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>dataSource 数据结构</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>文件唯一标识符(一般为 OSS ID)</td>\n<td>string</td>\n</tr>\n<tr>\n<td>uuid</td>\n<td>临时文件唯一标识符</td>\n<td>string</td>\n</tr>\n<tr>\n<td>type</td>\n<td>文件状态,值为 <code>\"uploading\"</code> 时显示上传中状态</td>\n<td>string</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>文件名称</td>\n<td>string</td>\n</tr>\n<tr>\n<td>date</td>\n<td>上传日期(时间戳或 Date 对象)</td>\n<td>Date | string</td>\n</tr>\n<tr>\n<td>userName</td>\n<td>上传人姓名</td>\n<td>string</td>\n</tr>\n</tbody>\n</table>\n<h3>OptionButtons 组件</h3>\n<p>文件操作按钮组,提供预览、编辑、删除等操作按钮。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>itemData</td>\n<td>文件数据对象</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>操作 API 配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onEdit</td>\n<td>编辑文件名称回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onPreview</td>\n<td>预览文件回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onDelete</td>\n<td>删除文件回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>hasPreview</td>\n<td>是否显示预览按钮</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>renderModal</td>\n<td>自定义 Modal 渲染函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FileLink 组件</h3>\n<p>文件链接组件,点击后弹出文件预览弹窗。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的访问地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>originName</td>\n<td>文件原始名称</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>预览弹窗标题</td>\n<td>string | ReactNode</td>\n<td>否</td>\n<td>originName</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>openDownload</td>\n<td>是否启用下载功能</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>Modal 组件的额外属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>链接文字内容,不传则显示 <code>originName</code></td>\n<td>ReactNode</td>\n<td>否</td>\n<td>originName</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>\n<h3>downloadBlobFile 函数</h3>\n<p>下载文件的工具函数。</p>\n<h4>函数签名</h4>\n<pre><code class=\"language-typescript\">downloadBlobFile(target: string | Blob, filename: string): void\n</code></pre>\n<h4>参数说明</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>target</td>\n<td>文件下载地址或二进制数据(Blob)</td>\n<td>string | Blob</td>\n<td>是</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>下载后的文件名</td>\n<td>string</td>\n<td>是</td>\n</tr>\n</tbody>\n</table>\n<h3>useDownload Hook</h3>\n<p>生成下载函数并管理下载状态的 Hook。</p>\n<h4>Hook 返回值</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>download</td>\n<td>执行下载的函数</td>\n<td>function</td>\n</tr>\n<tr>\n<td>isLoading</td>\n<td>是否正在下载</td>\n<td>boolean</td>\n</tr>\n<tr>\n<td>others</td>\n<td>其他 useFetch 返回的属性</td>\n<td>object</td>\n</tr>\n</tbody>\n</table>\n<h4>Hook 参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的下载地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>下载后的文件名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onSuccess</td>\n<td>下载成功回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onError</td>\n<td>下载失败回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>\n<h3>useFileModal Hook</h3>\n<p>生成文件预览弹窗函数的 Hook。</p>\n<h4>Hook 返回值</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>modal</td>\n<td>打开文件预览弹窗的函数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h4>modal 函数参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的访问地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>originName</td>\n<td>文件原始名称</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>预览弹窗标题</td>\n<td>string | ReactNode</td>\n<td>否</td>\n<td>originName</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>openDownload</td>\n<td>是否启用下载功能</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>Modal 组件的额外属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>\n<h3>FileButton 组件</h3>\n<p>文件按钮组件,点击后弹出文件预览弹窗。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件的唯一标识符</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>url</td>\n<td>直接指定文件的访问地址</td>\n<td>string</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>originName</td>\n<td>文件原始名称</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>预览弹窗标题</td>\n<td>string | ReactNode</td>\n<td>否</td>\n<td>originName</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>OSS 接口配置,包含 <code>oss</code> 属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>openDownload</td>\n<td>是否启用下载功能</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>Modal 组件的额外属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>type</td>\n<td>按钮类型</td>\n<td>string</td>\n<td>否</td>\n<td>default</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:<code>id</code> 和 <code>url</code> 至少需要传入其中一个。</p>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `获取文件地址`,\n description: `通过 OSS ID 获取文件访问地址,展示员工头像和公司 Logo 地址获取`,\n code: `const { default: File } = _File;\nconst { PureGlobal } = global;\nconst { getPublicPath } = remoteLoader;\nconst { Typography, Card, Space, Alert } = antd;\n\nconst { Paragraph, Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"文件地址获取示例\"\n description=\"演示如何通过 OSS ID 获取文件访问地址\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"员工头像地址\">\n <File id=\"employee-avatar-001\">\n {({ url, isLoading }) => (\n <Space direction=\"vertical\">\n <Text strong>访问地址:</Text>\n <Paragraph copyable>\n {isLoading ? '加载中...' : url}\n </Paragraph>\n </Space>\n )}\n </File>\n </Card>\n\n <Card title=\"公司 Logo 地址\">\n <File id=\"company-logo-main\">\n {({ url, isLoading }) => (\n <Space direction=\"vertical\">\n <Text strong>访问地址:</Text>\n <Paragraph copyable>\n {isLoading ? '加载中...' : url}\n </Paragraph>\n </Space>\n )}\n </File>\n </Card>\n </Space>\n );\n};\n\nrender(\n <PureGlobal\n preset={{\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n const mapping = {\n \"employee-avatar-001\": \"/avatar.png\",\n \"company-logo-main\": \"/mock/resume.pdf\"\n };\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + mapping[params.id] || \"\");\n }, 500);\n });\n },\n },\n },\n },\n }}\n >\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_File\",\n packageName: \"@components/File\",\n component: component_11\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_12\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_13\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_14\n}]\n},{\n title: `文件下载`,\n description: `展示不同类型文件的下载功能,包括成功和失败回调,人力资源相关文档下载`,\n code: `const { Download } = _File;\nconst { PureGlobal } = global;\nconst { getPublicPath } = remoteLoader;\nconst { Space, Card, Alert, Typography, message } = antd;\n\nconst { Title, Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"文件下载示例\"\n description=\"演示不同类型文件的下载功能,包括成功和失败回调\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"人力资源相关文档下载\">\n <Space direction=\"vertical\">\n <div>\n <Text type=\"secondary\">员工入职手册:</Text>\n <br />\n <Download\n id=\"doc-employee-handbook\"\n filename=\"员工入职手册.pdf\"\n onSuccess={() => message.success('员工入职手册下载成功')}\n onError={() => message.error('文件下载失败')}\n >\n 点击下载\n </Download>\n </div>\n\n <div>\n <Text type=\"secondary\">公司规章制度:</Text>\n <br />\n <Download\n id=\"doc-company-rules\"\n filename=\"公司规章制度.docx\"\n onSuccess={() => message.success('公司规章制度下载成功')}\n >\n 点击下载\n </Download>\n </div>\n\n <div>\n <Text type=\"secondary\">薪酬福利政策:</Text>\n <br />\n <Download\n id=\"doc-salary-policy\"\n filename=\"薪酬福利政策.pdf\"\n onSuccess={() => message.success('薪酬福利政策下载成功')}\n >\n 点击下载\n </Download>\n </div>\n </Space>\n </Card>\n </Space>\n );\n};\n\nrender(\n <PureGlobal\n preset={{\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + \"/avatar.png\");\n }, 800);\n });\n },\n },\n },\n },\n }}\n >\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_File\",\n packageName: \"@components/File\",\n component: component_11\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_12\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_13\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_14\n}]\n},{\n title: `文件列表`,\n description: `展示文件列表组件,支持上传状态、文件信息展示、编辑、预览、删除等操作,项目文档库和员工简历场景`,\n code: `const { List } = _FileList;\nconst { Space, Card, Alert, Typography } = antd;\nconst { PureGlobal } = global;\nconst { getPublicPath } = remoteLoader;\n\nconst { Title } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"文件列表示例\"\n description=\"展示文件上传状态、文件信息及操作功能\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"项目文档库\">\n <List\n dataSource={[\n {\n uuid: \"upload-001\",\n type: \"uploading\",\n filename: \"项目需求规格说明书.docx\",\n },\n {\n id: \"doc-project-plan\",\n filename: \"项目执行计划.pdf\",\n date: \"2024-01-15T10:30:00.000+08:00\",\n userName: \"张三\",\n },\n {\n id: \"doc-technical-design\",\n filename: \"技术架构设计文档.pdf\",\n date: \"2024-01-16T14:20:00.000+08:00\",\n userName: \"李四\",\n },\n {\n id: \"doc-api-interface\",\n filename: \"API 接口文档.md\",\n date: \"2024-01-17T09:15:00.000+08:00\",\n userName: \"王五\",\n },\n ]}\n apis={{\n onEdit: async (formData, itemData) => {\n console.log('编辑文件:', formData, itemData);\n },\n onDelete: async (itemData) => {\n console.log('删除文件:', itemData);\n },\n onPreview: async (itemData) => {\n console.log('预览文件:', itemData);\n },\n }}\n />\n </Card>\n\n <Card title=\"员工简历上传\">\n <List\n dataSource={[\n {\n id: \"resume-zhangsan\",\n filename: \"张三-高级前端工程师-简历.pdf\",\n date: \"2024-01-18T16:45:00.000+08:00\",\n userName: \"张三\",\n },\n {\n id: \"resume-lisi\",\n filename: \"李四-产品经理-简历.doc\",\n date: \"2024-01-19T11:20:00.000+08:00\",\n userName: \"李四\",\n },\n ]}\n apis={{\n onEdit: async (formData, itemData) => {\n console.log('编辑简历:', formData, itemData);\n },\n onDelete: async (itemData) => {\n console.log('删除简历:', itemData);\n },\n onPreview: async (itemData) => {\n console.log('预览简历:', itemData);\n },\n }}\n />\n </Card>\n </Space>\n );\n};\n\nrender(\n <PureGlobal\n preset={{\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + \"/mock/resume.pdf\");\n }, 600);\n });\n },\n },\n },\n },\n }}\n >\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_File\",\n packageName: \"@components/File\",\n component: component_11\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_12\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_13\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_14\n}]\n},{\n title: `文件链接`,\n description: `展示 FileLink 和 useFileModal 的使用,合同文档、财务发票、政策文档预览`,\n code: `const { FileLink, useFileModal } = _File;\nconst { getPublicPath } = remoteLoader;\nconst { PureGlobal } = global;\nconst { Space, Card, Alert, Typography, Button, Descriptions } = antd;\n\nconst { Title, Text } = Typography;\n\nconst CustomPreviewButton = ({ children, ...props }) => {\n const modal = useFileModal(props);\n return (\n <Button type=\"primary\" onClick={() => modal()}>\n {props.originName || children}\n </Button>\n );\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal\n preset={{\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n const mapping = {\n \"contract-001\": \"/avatar.png\",\n \"contract-002\": \"/mock/resume.pdf\",\n \"invoice-001\": \"/avatar.png\",\n \"policy-001\": \"/mock/resume.pdf\",\n };\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + (mapping[params.id] || \"\"));\n }, 500);\n });\n },\n },\n },\n },\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"文件链接示例\"\n description=\"展示 FileLink 和 useFileModal 的使用方式\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"合同文档(FileLink)\">\n <Space direction=\"vertical\">\n <FileLink\n id=\"contract-001\"\n originName=\"员工劳动合同.pdf\"\n />\n <FileLink\n id=\"contract-002\"\n originName=\"保密协议.docx\"\n />\n </Space>\n </Card>\n\n <Card title=\"财务发票(使用 useFileModal 自定义按钮)\">\n <Descriptions column={1} size=\"small\">\n <Descriptions.Item label=\"发票编号\">INV-2024-0001</Descriptions.Item>\n <Descriptions.Item label=\"开票日期\">2024-01-20</Descriptions.Item>\n <Descriptions.Item label=\"发票类型\">增值税专用发票</Descriptions.Item>\n </Descriptions>\n <div style={{ marginTop: 16 }}>\n <CustomPreviewButton\n id=\"invoice-001\"\n originName=\"查看发票详情\"\n />\n </div>\n </Card>\n\n <Card title=\"政策文档\">\n <Space direction=\"vertical\">\n <Text type=\"secondary\">点击下方链接预览公司政策文档:</Text>\n <FileLink\n id=\"policy-001\"\n originName=\"2024年度绩效考核管理办法.pdf\"\n />\n </Space>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_File\",\n packageName: \"@components/File\",\n component: component_11\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_13\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_12\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_14\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_19 from '@components/FileList';\nimport * as component_20 from '@kne/remote-loader';\nimport * as component_21 from 'lodash';\nimport * as component_22 from 'antd';\nconst readmeConfig = {\n name: `FileList`,\n summary: `<p>FileList 组件提供了一套完整的文件管理解决方案,集成了文件列表展示、文件预览、文件上传等功能。</p>\n<p>该组件支持拖拽上传、点击上传两种方式,提供了列表和预览两种视图模式。列表视图展示文件详细信息并支持编辑、删除、预览等操作,预览视图直接展示文件内容。组件内置了文件类型识别、上传进度管理、权限控制等功能,可以轻松集成到各种业务场景中。</p>\n<p>核心特性:</p>\n<ul>\n<li><strong>多视图模式</strong>:支持列表视图和预览视图切换,满足不同使用需求</li>\n<li><strong>拖拽上传</strong>:支持拖拽文件到指定区域进行上传,提升用户体验</li>\n<li><strong>文件预览</strong>:内置预览功能,支持多种文件格式的在线预览</li>\n<li><strong>权限控制</strong>:支持细粒度的权限控制,可控制添加、编辑、删除、预览等操作</li>\n<li><strong>灵活配置</strong>:支持自定义文件类型、文件大小限制、最大上传数量等参数</li>\n<li><strong>受控/非受控</strong>:同时支持受控和非受控模式,适应不同的使用场景</li>\n</ul>\n<p>适用于文档管理系统、人力资源系统、项目管理工具等需要文件处理的应用场景。</p>`,\n \n \n api: `<h3>FileList 组件</h3>\n<p>文件列表组件,提供文件展示、预览、上传等完整功能。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>list</td>\n<td>文件列表数据</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>setList</td>\n<td>更新文件列表的函数</td>\n<td>function</td>\n<td>否*</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultPreviewFileId</td>\n<td>默认预览的文件 ID</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultTab</td>\n<td>默认显示的标签页,可选值为 <code>\"list\"</code> 或 <code>\"preview\"</code></td>\n<td>string</td>\n<td>否</td>\n<td><code>\"list\"</code></td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大文件数量</td>\n<td>number</td>\n<td>否</td>\n<td>Number.MAX_VALUE</td>\n</tr>\n<tr>\n<td>fileSize</td>\n<td>单个文件最大大小(MB)</td>\n<td>number</td>\n<td>否</td>\n<td>20</td>\n</tr>\n<tr>\n<td>accept</td>\n<td>允许上传的文件类型数组</td>\n<td>array<string></td>\n<td>否</td>\n<td><code>[\".png\", \".jpg\", \".pdf\", \".docx\", \".doc\"]</code></td>\n</tr>\n<tr>\n<td>getPermission</td>\n<td>权限控制函数,接收参数 <code>(type, itemData)</code>,返回 <code>false</code> 表示无权限</td>\n<td>function</td>\n<td>否</td>\n<td><code>() => true</code></td>\n</tr>\n<tr>\n<td>infoItemRenders</td>\n<td>自定义列渲染配置</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>操作 API 配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onSave</td>\n<td>保存文件回调,接收参数 <code>(response, ...args)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onEdit</td>\n<td>编辑文件名称回调,接收参数 <code>({formData, item})</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onPreview</td>\n<td>预览文件回调,接收参数 <code>(item)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onDelete</td>\n<td>删除文件回调,接收参数 <code>(item)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onUpload</td>\n<td>文件上传回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>titleExtra</td>\n<td>标题额外内容,可以是 ReactNode 或函数</td>\n<td>ReactNode | function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>getPopupContainer</td>\n<td>指定下拉菜单挂载的父节点</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>注意</strong>:使用受控模式时需要同时提供 <code>list</code> 和 <code>setList</code> 属性。</p>\n<h4>list 数据结构</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>文件唯一标识符</td>\n<td>string</td>\n</tr>\n<tr>\n<td>ossId</td>\n<td>OSS 文件标识符</td>\n<td>string</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>文件名称</td>\n<td>string</td>\n</tr>\n<tr>\n<td>date</td>\n<td>上传日期(时间戳或 Date 对象)</td>\n<td>Date | string</td>\n</tr>\n<tr>\n<td>userName</td>\n<td>上传人姓名</td>\n<td>string</td>\n</tr>\n</tbody>\n</table>\n<h3>FileUpload 组件</h3>\n<p>简化的文件上传组件,专注于文件上传和列表展示功能。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>list</td>\n<td>文件列表数据</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultList</td>\n<td>默认文件列表数据</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>setList</td>\n<td>更新文件列表的函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大文件数量</td>\n<td>number</td>\n<td>否</td>\n<td>Number.MAX_VALUE</td>\n</tr>\n<tr>\n<td>fileSize</td>\n<td>单个文件最大大小(MB)</td>\n<td>number</td>\n<td>否</td>\n<td>20</td>\n</tr>\n<tr>\n<td>accept</td>\n<td>允许上传的文件类型数组</td>\n<td>array<string></td>\n<td>否</td>\n<td><code>[\".png\", \".jpg\", \".pdf\", \".docx\", \".doc\"]</code></td>\n</tr>\n<tr>\n<td>getPermission</td>\n<td>权限控制函数,接收参数 <code>(type, itemData)</code>,返回 <code>false</code> 表示无权限</td>\n<td>function</td>\n<td>否</td>\n<td><code>() => true</code></td>\n</tr>\n<tr>\n<td>apis</td>\n<td>操作 API 配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onSave</td>\n<td>保存文件回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onEdit</td>\n<td>编辑文件名称回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onPreview</td>\n<td>预览文件回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis.onDelete</td>\n<td>删除文件回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>DragArea 组件</h3>\n<p>拖拽上传区域组件。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>拖拽区域内显示的内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td><code><UploadTips /></code></td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>DragAreaOuter 组件</h3>\n<p>拖拽上传区域外层容器组件。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>标题内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>accept</td>\n<td>允许上传的文件类型数组</td>\n<td>array<string></td>\n<td>否</td>\n<td><code>[\".png\", \".jpg\", \".pdf\", \".docx\", \".doc\"]</code></td>\n</tr>\n<tr>\n<td>fileSize</td>\n<td>单个文件最大大小(MB)</td>\n<td>number</td>\n<td>否</td>\n<td>20</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大文件数量</td>\n<td>number</td>\n<td>否</td>\n<td>Number.MAX_VALUE</td>\n</tr>\n<tr>\n<td>onFileSelected</td>\n<td>文件选择回调,接收参数 <code>(fileList)</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultOpen</td>\n<td>默认是否打开拖拽区域</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>DragButton 组件</h3>\n<p>拖拽上传按钮组件。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>按钮文字内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>UploadButton 组件</h3>\n<p>点击上传按钮组件。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>按钮文字内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>UploadTips 组件</h3>\n<p>上传提示组件,显示上传说明信息。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>icon</td>\n<td>自定义图标</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>提示标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>renderTips</td>\n<td>自定义提示内容渲染函数,接收参数 <code>(defaultTips, {fileSize, maxLength, accept})</code></td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `完整示例`,\n description: `展示完整的文件列表功能,包含文件展示、预览、上传、编辑、删除等操作,员工简历、合同、政策文档场景`,\n code: `const { default: FileList } = _FileList;\nconst { createWithRemoteLoader, getPublicPath } = remoteLoader;\nconst { useState } = React;\nconst { uniqueId } = lodash;\n\nconst ajax = {\n postForm: (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n data: {\n code: 0,\n data: {\n id: \"uBFNeYQBnHRXlZaTGZpA\",\n originalName: config.file.name,\n },\n },\n });\n }, 800);\n });\n },\n};\n\nconst apis = {\n onSave: async ({ data }) => {\n return {\n ossId: uniqueId(\"oss_\"),\n filename: data.originalName,\n date: new Date(),\n userName: \"张三\",\n };\n },\n onDelete: (item) => {\n console.log('删除文件:', item);\n },\n};\n\nconst preset = {\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n const mapping = {\n \"resume-zhangsan\": \"/mock/resume.pdf\",\n \"contract-employee\": \"/avatar.png\",\n \"policy-2024\": \"/mock/resume.pdf\",\n };\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + mapping[params.id] || \"\");\n }, 100);\n });\n },\n },\n },\n previewOffice: {\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n name: \"员工入职登记表.docx\",\n data: [\n {\n id: \"doc-preview-001\",\n originalName: \"preview.pdf\",\n url: getPublicPath(\"components-core\") + \"/mock/resume.pdf\",\n },\n ],\n });\n }, 0);\n });\n },\n },\n ossUpload: ({ file }) => {\n return ajax.postForm({ file });\n },\n },\n};\n\nconst BaseExample = createWithRemoteLoader({\n modules: [\"components-core:Global@PureGlobal\"],\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n const [list, setList] = useState([\n {\n id: \"resume-zhangsan\",\n filename: \"张三-高级前端工程师-简历.pdf\",\n date: \"2024-01-15T10:30:00.000+08:00\",\n userName: \"张三\",\n },\n {\n id: \"contract-employee\",\n filename: \"劳动合同模板.docx\",\n date: \"2024-01-16T14:20:00.000+08:00\",\n userName: \"李四\",\n },\n {\n id: \"policy-2024\",\n filename: \"2024年度绩效考核管理办法.pdf\",\n date: \"2024-01-17T09:15:00.000+08:00\",\n userName: \"王五\",\n },\n ]);\n return (\n <PureGlobal preset={preset}>\n <FileList\n defaultPreviewFileId=\"resume-zhangsan\"\n list={list}\n setList={setList}\n apis={apis}\n titleExtra={({ currentTab, currentPreviewFileId }) => (\n <span style={{ fontSize: '12px', color: '#999' }}>\n {currentTab === 'preview' ? '预览模式' : '列表模式'}\n {currentPreviewFileId && \\` | 当前: \\${list.find(f => f.id === currentPreviewFileId)?.filename}\\`}\n </span>\n )}\n />\n </PureGlobal>\n );\n});\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FileList\",\n packageName: \"@components/FileList\",\n component: component_19\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_20\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_21\n}]\n},{\n title: `文件上传`,\n description: `展示受控和非受控模式的文件上传功能,支持设置文件大小和数量限制`,\n code: `const { FileUpload } = _FileList;\nconst { createWithRemoteLoader, getPublicPath } = remoteLoader;\nconst { useState } = React;\nconst { uniqueId } = lodash;\nconst { Space, Typography, Alert } = antd;\n\nconst { Text } = Typography;\n\nconst ajax = {\n postForm: (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n data: {\n code: 0,\n data: {\n id: \"uBFNeYQBnHRXlZaTGZpA\",\n originalName: config.file.name,\n },\n },\n });\n }, 800);\n });\n },\n};\n\nconst apis = {\n onSave: async ({ data }) => {\n return {\n ossId: uniqueId(\"oss_\"),\n filename: data.originalName,\n date: new Date(),\n userName: \"张三\",\n };\n },\n onDelete: (item) => {\n console.log('删除文件:', item);\n },\n};\n\nconst preset = {\n apis: {\n file: {\n getUrl: {\n loader: async ({ params }) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(getPublicPath(\"components-core\") + \"/avatar.png\");\n }, 500);\n });\n },\n },\n },\n ossUpload: ({ file }) => {\n return ajax.postForm({ file });\n },\n },\n};\n\nconst BaseExample = createWithRemoteLoader({\n modules: [\"components-core:Global@PureGlobal\"],\n})(({ remoteModules }) => {\n const [PureGlobal] = remoteModules;\n const [list, setList] = useState([]);\n const [uncontrolledList, setUncontrolledList] = useState([]);\n\n return (\n <PureGlobal preset={preset}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"文件上传示例\"\n description=\"展示受控和非受控模式的文件上传功能\"\n type=\"info\"\n showIcon\n />\n\n <div>\n <Text strong>受控模式:</Text>\n <Text type=\"secondary\" style={{ marginLeft: 8 }}>\n 通过 list 和 setList 完全控制文件列表\n </Text>\n <FileUpload\n list={list}\n setList={setList}\n apis={apis}\n fileSize={10}\n maxLength={5}\n />\n <div style={{ marginTop: 8, padding: '12px', background: '#f5f5f5', borderRadius: '4px' }}>\n <Text type=\"secondary\">当前文件数量:{list.length}</Text>\n </div>\n </div>\n\n <div>\n <Text strong>非受控模式:</Text>\n <Text type=\"secondary\" style={{ marginLeft: 8 }}>\n 只通过 setList 接收变化,不传入 list\n </Text>\n <FileUpload\n setList={(fileList) => {\n setUncontrolledList(fileList);\n }}\n apis={apis}\n fileSize={10}\n />\n <div style={{ marginTop: 8, padding: '12px', background: '#f5f5f5', borderRadius: '4px' }}>\n <Text type=\"secondary\">当前文件数量:{uncontrolledList.length}</Text>\n </div>\n </div>\n </Space>\n </PureGlobal>\n );\n});\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FileList\",\n packageName: \"@components/FileList\",\n component: component_19\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_20\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_21\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_22\n}]\n},{\n title: `拖拽上传`,\n description: `展示拖拽上传功能,支持自定义上传提示,项目文档和员工资料上传场景`,\n code: `const { DragArea, DragAreaOuter, UploadButton, DragButton, UploadTips } = _FileList;\nconst { Row, Col, Divider, Space, Typography, Alert, Card, message } = antd;\n\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"拖拽上传示例\"\n description=\"支持拖拽文件到指定区域进行上传,或使用按钮点击上传\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"项目文档上传\">\n <DragAreaOuter\n title={\n <Row>\n <Col flex={1}>\n <Text strong>上传项目文档</Text>\n </Col>\n <Col>\n <Space split={<Divider type=\"vertical\" />}>\n <DragButton />\n <UploadButton>选择文件</UploadButton>\n </Space>\n </Col>\n </Row>\n }\n onFileSelected={(fileList) => {\n message.success(\\`已选择 \\${fileList.length} 个文件\\`);\n console.log('选中的文件:', fileList);\n }}\n fileSize={10}\n maxLength={10}\n >\n <DragArea>\n <UploadTips\n icon={<span style={{ fontSize: '48px' }}>📁</span>}\n title=\"拖拽文件到这里\"\n renderTips={(defaultTips, { fileSize, maxLength }) => (\n <div>\n <div>{defaultTips}</div>\n <Text type=\"secondary\" style={{ fontSize: '12px' }}>\n 支持批量上传,最多 {maxLength} 个文件\n </Text>\n </div>\n )}\n />\n </DragArea>\n </DragAreaOuter>\n </Card>\n\n <Card title=\"员工资料上传\">\n <DragAreaOuter\n title={\n <Row>\n <Col flex={1}>\n <Text strong>上传员工资料</Text>\n </Col>\n <Col>\n <Space split={<Divider type=\"vertical\" />}>\n <DragButton />\n <UploadButton>选择文件</UploadButton>\n </Space>\n </Col>\n </Row>\n }\n onFileSelected={(fileList) => {\n message.success(\\`已选择 \\${fileList.length} 个文件\\`);\n console.log('选中的文件:', fileList);\n }}\n fileSize={5}\n accept={['.pdf', '.jpg', '.png', '.docx']}\n >\n <DragArea />\n </DragAreaOuter>\n </Card>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FileList\",\n packageName: \"@components/FileList\",\n component: component_19\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_22\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_23 from '@components/FilePreview';\nimport * as component_24 from '@kne/remote-loader';\nimport * as component_25 from '@components/Global';\nconst readmeConfig = {\n name: `FilePreview`,\n summary: `<p>FilePreview 是一个功能全面的文件预览组件库,支持多种常见文件格式的在线预览。该组件基于 @kne/react-file 封装,提供了统一的 API 接口,可根据文件类型自动选择合适的预览方式,极大简化了文件预览功能的集成。</p>\n<p>核心特性包括:支持图片、音频、视频、PDF、HTML、文本和 Office 文档等多种格式;提供 OSS 文件预览能力,通过文件 ID 自动获取预览地址;响应式设计,自动适配容器宽度;完善的加载状态和错误提示;支持自定义 PDF 渲染参数和 Office 预览配置。</p>\n<p>适用于文档管理系统、在线办公平台、内容管理系统等需要文件预览功能的场景,特别适合需要处理多种文件类型的企业级应用。组件采用模块化设计,可以独立使用各个预览组件,也可使用统一的 FilePreview 组件自动判断文件类型。</p>`,\n \n \n api: `<h3>FilePreview 组件</h3>\n<p>智能文件预览组件,根据文件类型自动选择对应的预览方式。支持直接传入文件 URL 或 OSS 文件 ID 两种方式。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>src</td>\n<td>文件预览地址,优先使用该参数</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>id</td>\n<td>OSS 文件标识符,当 src 未提供时使用</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>originName</td>\n<td>原始文件名,用于判断文件类型</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>文件名,用于判断文件类型</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>OSSFilePreview 组件</h3>\n<p>OSS 文件预览组件,通过文件 ID 从服务器获取文件地址后进行预览。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>OSS 文件标识符</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>filename</td>\n<td>文件名,用于判断文件类型</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>staticUrl</td>\n<td>静态文件地址前缀</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>render</td>\n<td>自定义渲染函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>HtmlPreview 组件</h3>\n<p>HTML 文件预览组件,支持在 iframe 中展示 HTML 内容。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>HTML 文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>ignoreContent</td>\n<td>是否忽略内容检查,直接使用 iframe</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>PdfPreview 组件</h3>\n<p>PDF 文件预览组件,基于 react-pdf 实现,支持缩放和旋转。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>PDF 文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>scale</td>\n<td>缩放比例(100 为原始大小)</td>\n<td>number</td>\n<td>否</td>\n<td>100</td>\n</tr>\n<tr>\n<td>rotate</td>\n<td>旋转角度</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n</tr>\n<tr>\n<td>pdfjsUrl</td>\n<td>pdf.js CDN 地址</td>\n<td>string</td>\n<td>否</td>\n<td>https://cdn.jsdelivr.net/npm/pdfjs-dist@5.4.296</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TextPreview 组件</h3>\n<p>文本文件预览组件,支持纯文本文件的在线展示。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>文本文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>ImagePreview 组件</h3>\n<p>图片预览组件,支持常见图片格式的展示。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>图片地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>scale</td>\n<td>缩放比例</td>\n<td>number</td>\n<td>否</td>\n<td>1</td>\n</tr>\n<tr>\n<td>rotate</td>\n<td>旋转角度</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n</tr>\n<tr>\n<td>origin</td>\n<td>是否使用原生 img 标签,不带容器和加载状态</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>AudioPreview 组件</h3>\n<p>音频预览组件,使用原生 audio 标签进行音频播放。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>音频文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>VideoPreview 组件</h3>\n<p>视频预览组件,使用原生 video 标签进行视频播放。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>视频文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n<tr>\n<td>controls</td>\n<td>是否显示播放控件</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>origin</td>\n<td>是否使用原生 video 标签,不带容器</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>getElement</td>\n<td>获取 video 元素的回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>OfficePreview 组件</h3>\n<p>Office 文件预览组件,使用 Office Online Viewer 进行预览。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>url</td>\n<td>Office 文件地址</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>API 配置对象,可配置自定义预览服务</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>UnknownPreview 组件</h3>\n<p>未知类型文件预览组件,用于不支持预览的文件类型。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>maxWidth</td>\n<td>最大显示宽度</td>\n<td>number</td>\n<td>否</td>\n<td>1200</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `HtmlPreview`,\n description: `这里填写示例说明`,\n code: `const { default: FilePreview, HtmlPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <HtmlPreview\n maxWidth={900}\n url={getPublicPath(\"components-core\") + \"/mock/demo2.html\"}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n}]\n},{\n title: `PdfPreview`,\n description: `这里填写示例说明`,\n code: `const { PdfPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <PdfPreview\n maxWidth={900}\n url={getPublicPath(\"components-core\") + \"/mock/resume.pdf\"}\n renderTextLayer={true}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n}]\n},{\n title: `TextPreview`,\n description: `这里填写示例说明`,\n code: `const { TextPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <TextPreview\n maxWidth={900}\n url={getPublicPath(\"components-core\") + \"/mock/demo.txt\"}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n}]\n},{\n title: `ImagePreview`,\n description: `这里填写示例说明`,\n code: `const { ImagePreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <ImagePreview url={getPublicPath(\"components-core\") + \"/mock/resume.png\"} />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n}]\n},{\n title: `unknown`,\n description: `这里填写示例说明`,\n code: `const { UnknownPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <UnknownPreview url={getPublicPath(\"components-core\") + \"/mock/demo.des\"} />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n}]\n},{\n title: `office`,\n description: `这里填写示例说明`,\n code: `const {default: FilePreview} = _FilePreview;\nconst {getPublicPath} = remoteLoader;\nconst {PureGlobal} = _Global;\nconst BaseExample = () => {\n return (\n <PureGlobal\n preset={{\n apis: {\n file: {\n getUrl: {\n loader:()=>{\n return \"http://ieee802.org:80/secmail/docIZSEwEqHFr.doc\";\n },\n },\n },\n },\n }}\n >\n <FilePreview\n id=\"63bb2013-c743-4d2d-9d91-935c865f1c4d\"\n originName=\"docIZSEwEqHFr.doc\"\n />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_25\n}]\n},{\n title: `audio`,\n description: `这里填写示例说明`,\n code: `const { AudioPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <AudioPreview\n maxWidth={900}\n url={getPublicPath(\"components-core\") + \"/mock/audio.wav\"}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_25\n}]\n},{\n title: `video`,\n description: `这里填写示例说明`,\n code: `const { VideoPreview } = _FilePreview;\nconst { getPublicPath } = remoteLoader;\nconst BaseExample = () => {\n return (\n <VideoPreview\n maxWidth={900}\n url={getPublicPath(\"components-core\") + \"/mock/video.mp4\"}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FilePreview\",\n packageName: \"@components/FilePreview\",\n component: component_23\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_24\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_25\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_15 from '@components/Filter';\nimport * as component_16 from '@components/Enum';\nimport * as component_17 from 'antd';\nimport * as component_18 from '@components/Filter/doc/mock/tree-data.json';\nconst readmeConfig = {\n name: `Filter`,\n summary: `<p>Filter 是一个功能强大的筛选组件库,用于构建灵活的筛选条件界面。该组件提供了多种预置的筛选字段类型,支持自定义筛选项,并提供了完整的筛选值管理和展示功能。</p>\n<p>核心特性包括:丰富的预置筛选字段,涵盖文本输入、日期选择、城市选择、用户选择、行业选择、职能选择等多种类型;灵活的筛选值管理,支持受控和非受控模式;支持展开/收起筛选项,避免筛选条件过多导致界面混乱;提供高级筛选组件,适用于复杂筛选场景;支持自定义字段和组合使用,满足各种业务需求;内置搜索输入框和筛选值展示组件,提升用户体验。</p>\n<p>适用于数据列表、表格筛选、报表查询等需要多条件筛选的场景。组件采用 Context API 进行状态管理,支持嵌套使用和组合,能够满足企业级应用中各种复杂的筛选需求。</p>`,\n \n \n api: `<h3>Filter 组件</h3>\n<p>筛选组件的主入口,用于构建灵活的筛选条件界面。支持受控和非受控模式,自动管理筛选值状态。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>筛选值数组,受控模式使用</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>筛选值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultValue</td>\n<td>默认筛选值</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>list</td>\n<td>筛选项配置数组,支持多行布局</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>displayLine</td>\n<td>默认显示的行数,超过则支持展开/收起</td>\n<td>number</td>\n<td>否</td>\n<td>1</td>\n</tr>\n<tr>\n<td>label</td>\n<td>筛选标题,默认显示\"筛选\"</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>extra</td>\n<td>额外内容,通常用于放置搜索输入框等</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>extraExpand</td>\n<td>额外展开内容,显示在已选筛选值右侧</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>value 数据结构</h4>\n<p>筛选值数组中每个元素的结构:</p>\n<pre><code class=\"language-javascript\">{\n name: 'city', // 筛选字段名\n label: '城市', // 筛选项标签\n value: [ // 筛选值,可以是单个值或数组\n { label: '上海', value: '010' },\n { label: '北京', value: '020' }\n ]\n}\n</code></pre>\n<h3>AdvancedFilter 组件</h3>\n<p>高级筛选组件,适用于需要展示多个筛选条件且支持展开/收起的场景。相比普通 Filter 组件,提供更紧凑的布局。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>筛选值数组</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>筛选值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultValue</td>\n<td>默认筛选值</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>list</td>\n<td>筛选项配置数组</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>more</td>\n<td>更多筛选项,支持展开/收起</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FilterLines 组件</h3>\n<p>筛选项布局组件,用于按照行展示筛选项,支持展开/收起功能。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>list</td>\n<td>筛选项配置数组,支持多行布局</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>displayLine</td>\n<td>默认显示的行数</td>\n<td>number</td>\n<td>否</td>\n<td>1</td>\n</tr>\n<tr>\n<td>label</td>\n<td>筛选标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>extra</td>\n<td>额外内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FilterValueDisplay 组件</h3>\n<p>筛选值展示组件,用于展示已选择的筛选条件,支持单个删除和清空全部。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>筛选值数组</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>筛选值变化回调函数</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>extraExpand</td>\n<td>额外展开内容,显示在清空按钮左侧</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FilterItem 组件</h3>\n<p>筛选项容器组件,提供统一的样式和交互效果。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>筛选项标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>open</td>\n<td>是否打开下拉</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>active</td>\n<td>是否激活状态(有选中值时自动激活)</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>筛选项内容</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>PopoverItem 组件</h3>\n<p>弹出式筛选项组件,基于 Popover 实现。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>筛选项标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>渲染函数,接收 { value, onChange } 参数</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>SearchInput 组件</h3>\n<p>搜索输入框组件,通常用于放置在筛选器右侧的搜索功能。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>输入框占位符</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>输入框值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FilterItemContainer 组件</h3>\n<p>筛选项容器组件,用于包装需要传递额外属性的筛选项。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>渲染函数,接收筛选项 props</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>InputFilterItem 组件</h3>\n<p>文本输入筛选项组件,用于文本类型的筛选。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>输入框占位符</td>\n<td>string</td>\n<td>否</td>\n<td>请输入{label}</td>\n</tr>\n<tr>\n<td>value</td>\n<td>输入框值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>DatePickerFilterItem 组件</h3>\n<p>日期选择筛选项组件,支持多种日期选择模式。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>picker</td>\n<td>日期选择器类型,可选值:<code>date</code>、<code>week</code>、<code>month</code>、<code>quarter</code>、<code>year</code></td>\n<td>string</td>\n<td>否</td>\n<td><code>date</code></td>\n</tr>\n<tr>\n<td>value</td>\n<td>日期值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>DateRangePickerFilterItem 组件</h3>\n<p>日期范围选择筛选项组件,用于选择日期范围。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>日期范围值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TypeDateRangePickerFilterItem 组件</h3>\n<p>类型化日期范围选择筛选项组件,支持日期类型选择(如创建时间、更新时间等)。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>allowEmpty</td>\n<td>是否允许清空 [开始时间清空, 结束时间清空]</td>\n<td>array</td>\n<td>否</td>\n<td>[false, false]</td>\n</tr>\n<tr>\n<td>value</td>\n<td>日期范围值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>CityFilterItem 组件</h3>\n<p>城市选择筛选项组件,支持省市区三级联动选择。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>城市值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<h3>NumberRangeFilterItem 组件</h3>\n<p>数值范围筛选项组件,用于选择数值范围。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>unit</td>\n<td>数值单位</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>数值范围值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>AdvancedSelectFilterItem 组件</h3>\n<p>高级选择筛选项组件,支持远程数据加载、分页、搜索等功能。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api.loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>选择值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>SuperSelectFilterItem 组件</h3>\n<p>超级选择筛选项组件,支持展示描述信息、图标等丰富的选项内容。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>options</td>\n<td>选项数据数组</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>选择值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>UserFilterItem 组件</h3>\n<p>用户选择筛选项组件,专门用于用户选择场景。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api.loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>用户值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>SuperSelectUserFilterItem 组件</h3>\n<p>超级用户选择筛选项组件,支持展示用户描述信息。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api.loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>用户值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FunctionSelectFilterItem 组件</h3>\n<p>职能选择筛选项组件,用于选择职能信息。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>selectLevel</td>\n<td>选择层级</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大选择数量</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>onlyAllowLastLevel</td>\n<td>是否只允许选择最后一级</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>value</td>\n<td>职能值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>IndustrySelectFilterItem 组件</h3>\n<p>行业选择筛选项组件,用于选择行业信息。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>selectLevel</td>\n<td>选择层级</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大选择数量</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>onlyAllowLastLevel</td>\n<td>是否只允许选择最后一级</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>value</td>\n<td>行业值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>CascaderFilterItem 组件</h3>\n<p>级联选择筛选项组件,用于级联数据的选择。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>options</td>\n<td>选项数据数组</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>选择值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TreeFilterItem 组件</h3>\n<p>树形选择筛选项组件,用于树形结构数据的选择。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>API 配置对象</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api.loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>fieldNames</td>\n<td>字段名映射</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>fieldNames.title</td>\n<td>标题字段名</td>\n<td>string</td>\n<td>否</td>\n<td><code>title</code></td>\n</tr>\n<tr>\n<td>fieldNames.key</td>\n<td>键字段名</td>\n<td>string</td>\n<td>否</td>\n<td><code>key</code></td>\n</tr>\n<tr>\n<td>fieldNames.children</td>\n<td>子节点字段名</td>\n<td>string</td>\n<td>否</td>\n<td><code>children</code></td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>value</td>\n<td>选择值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>高级字段组件</h3>\n<h4>ListFilterItem 组件(AdvancedFilter.fields)</h4>\n<p>列表选择筛选项组件,以标签形式展示选项,支持单选和多选。</p>\n<h4>组件属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items</td>\n<td>选项数据数组</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大选择数量</td>\n<td>number</td>\n<td>否</td>\n<td>5</td>\n</tr>\n<tr>\n<td>custom</td>\n<td>自定义筛选项</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>value</td>\n<td>选择值</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>值变化回调函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>工具函数</h3>\n<h4>getFilterValue</h4>\n<p>将筛选值数组转换为对象格式。</p>\n<p><strong>函数签名:</strong></p>\n<pre><code class=\"language-javascript\">getFilterValue(filterValue: array): object\n</code></pre>\n<p><strong>参数说明:</strong></p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>filterValue</td>\n<td>筛选值数组</td>\n<td>array</td>\n</tr>\n</tbody>\n</table>\n<p><strong>返回值:</strong></p>\n<p>转换后的对象,格式为 <code>{ name: value, ... }</code>,其中 value 是提取的值数组或单个值。</p>\n<p><strong>示例:</strong></p>\n<pre><code class=\"language-javascript\">const filterValue = [\n { name: 'city', value: [{ label: '上海', value: '010' }] },\n { name: 'text', value: { label: '测试', value: 'test' } }\n];\nconst result = getFilterValue(filterValue);\n// result: { city: ['010'], text: 'test' }\n</code></pre>\n<h4>useFilter</h4>\n<p>获取筛选上下文的 Hook。</p>\n<p><strong>函数签名:</strong></p>\n<pre><code class=\"language-javascript\">useFilter(): object\n</code></pre>\n<p><strong>返回值:</strong></p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>筛选值 Map</td>\n<td>Map</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>筛选值变化函数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h4>withFilterValue</h4>\n<p>高阶组件,用于自动连接筛选上下文。</p>\n<p><strong>函数签名:</strong></p>\n<pre><code class=\"language-javascript\">withFilterValue(WrappedComponent): ReactComponent\n</code></pre>\n<p><strong>参数说明:</strong></p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>WrappedComponent</td>\n<td>被包装的组件</td>\n<td>ReactComponent</td>\n</tr>\n</tbody>\n</table>\n<p><strong>新增 Props:</strong></p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n</tr>\n</tbody>\n</table>\n<h4>withFieldItem</h4>\n<p>高阶组件,用于将表单字段组件包装为筛选项组件。</p>\n<p><strong>函数签名:</strong></p>\n<pre><code class=\"language-javascript\">withFieldItem(WrappedComponent): ReactComponent\n</code></pre>\n<p><strong>参数说明:</strong></p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>WrappedComponent</td>\n<td>被包装的组件</td>\n<td>ReactComponent</td>\n</tr>\n</tbody>\n</table>\n<p><strong>新增 Props:</strong></p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>string</td>\n</tr>\n<tr>\n<td>interceptor</td>\n<td>拦截器,用于值转换</td>\n<td>object</td>\n</tr>\n<tr>\n<td>interceptor.input</td>\n<td>输入拦截器</td>\n<td>function</td>\n</tr>\n<tr>\n<td>interceptor.output</td>\n<td>输出拦截器</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `基础用法`,\n description: `展示 Filter 组件的基本使用方式,包括各种常见的筛选字段类型`,\n code: `const {\n default: Filter,\n InputFilterItem,\n DatePickerFilterItem,\n DateRangePickerFilterItem,\n TypeDateRangePickerFilterItem,\n CityFilterItem,\n AdvancedSelectFilterItem,\n SuperSelectFilterItem,\n SuperSelectUserFilterItem,\n UserFilterItem,\n FunctionSelectFilterItem,\n IndustrySelectFilterItem,\n getFilterValue,\n FilterItemContainer,\n} = _Filter;\nconst { useState } = React;\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n return (\n <Filter\n value={value}\n onChange={(value) => {\n console.log(getFilterValue(value));\n onChange(value);\n }}\n extra={<Filter.SearchInput name=\"name\" label=\"姓名\" />}\n list={[\n [\n <InputFilterItem label=\"文字\" name=\"text\" />,\n <CityFilterItem label=\"城市\" name=\"city\" />,\n <FilterItemContainer name=\"select\" label=\"高级选择\">\n {(props) => (\n <div>\n <AdvancedSelectFilterItem\n {...props}\n api={{\n loader: () => {\n return {\n pageData: [\n { label: \"第一项\", value: 1 },\n {\n label: \"第二项\",\n value: 2,\n disabled: true,\n },\n {\n label: \"第三项\",\n value: 3,\n },\n ],\n };\n },\n }}\n />\n </div>\n )}\n </FilterItemContainer>,\n <DatePickerFilterItem label=\"日期\" name=\"date\" picker=\"week\" />,\n <TypeDateRangePickerFilterItem\n label=\"复杂日期范围\"\n name=\"type-data-range\"\n allowEmpty={[true, true]}\n />,\n <DateRangePickerFilterItem label=\"日期范围\" name=\"date-range\" />,\n <SuperSelectFilterItem\n label=\"选择信息\"\n name=\"select-value\"\n options={[\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n ]}\n />,\n <SuperSelectUserFilterItem\n label=\"用户选择\"\n name=\"user\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n {\n label: \"用户三\",\n value: 3,\n description: \"我是用户描述\",\n },\n ],\n };\n },\n }}\n />,\n <FunctionSelectFilterItem\n label=\"职能选择\"\n name=\"functionLast\"\n onlyAllowLastLevel\n />,\n <FunctionSelectFilterItem\n label=\"职能选择\"\n name=\"function\"\n selectLevel={3}\n maxLength={3}\n />,\n <FunctionSelectFilterItem\n label=\"职能选择\"\n name=\"functionSingle\"\n single\n />,\n <IndustrySelectFilterItem\n label=\"行业选择\"\n name=\"industryLast\"\n onlyAllowLastLevel\n />,\n <IndustrySelectFilterItem\n label=\"行业选择\"\n name=\"industry\"\n selectLevel={2}\n maxLength={3}\n />,\n <IndustrySelectFilterItem\n label=\"行业选择\"\n name=\"industrySingle\"\n single\n />,\n ],\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n}]\n},{\n title: `展示和Enum一起使用`,\n description: ``,\n code: `const {\n default: Filter, SuperSelectFilterItem, getFilterValue\n} = _Filter;\nconst {default: Enum} = _Enum;\nconst {useState} = React;\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n return (<Filter\n value={value}\n onChange={(value) => {\n console.log(getFilterValue(value));\n onChange(value);\n }}\n list={[[<SuperSelectFilterItem name=\"degree\" label=\"学历\" render={({children}) => {\n return <Enum moduleName=\"degreeEnum\" format=\"option\">{(options) => children({options})}</Enum>\n }}/>]]}\n />);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n},{\n name: \"_Enum\",\n packageName: \"@components/Enum\",\n component: component_16\n}]\n},{\n title: `高级筛选`,\n description: `展示 AdvancedFilter 组件的高级筛选功能,适用于复杂筛选场景`,\n code: `const {\n default: Filter,\n AdvancedFilter,\n InputFilterItem,\n DatePickerFilterItem,\n DateRangePickerFilterItem,\n TypeDateRangePickerFilterItem,\n CityFilterItem,\n AdvancedSelectFilterItem,\n UserFilterItem,\n FunctionSelectFilterItem,\n IndustrySelectFilterItem,\n NumberRangeFilterItem,\n getFilterValue,\n FilterItemContainer,\n} = _Filter;\nconst { useState } = React;\n\nconst {\n CityFilterItem: CityAdvancedFilterItem,\n ListFilterItem,\n InputFilterItem: InputAdvancedFilterItem,\n} = AdvancedFilter.fields;\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n return (\n <AdvancedFilter\n value={value}\n onChange={(value) => {\n console.log(getFilterValue(value));\n onChange(value);\n }}\n list={[\n [<CityAdvancedFilterItem name=\"currentCity\" label=\"当前城市\" single />],\n [<CityAdvancedFilterItem name=\"expectCity\" label=\"期望城市\" />],\n [\n <ListFilterItem\n name=\"experience\"\n label=\"工作经验\"\n single\n items={[\n {\n value: [null, 1],\n label: \"1年以下\",\n },\n {\n value: [1, 5],\n label: \"1-5年\",\n },\n { value: [5, null], label: \"5年以上\" },\n ]}\n custom={<NumberRangeFilterItem label=\"自定义\" unit=\"年\" />}\n />,\n ],\n [<InputAdvancedFilterItem name=\"company\" label=\"公司\" />],\n ]}\n more={[\n <InputFilterItem label=\"文字\" name=\"text\" />,\n <CityFilterItem label=\"城市\" name=\"city\" />,\n <FilterItemContainer name=\"select\" label=\"高级选择\">\n {(props) => (\n <div>\n <AdvancedSelectFilterItem\n {...props}\n api={{\n loader: () => {\n return {\n pageData: [\n { label: \"第一项\", value: 1 },\n {\n label: \"第二项\",\n value: 2,\n disabled: true,\n },\n {\n label: \"第三项\",\n value: 3,\n },\n ],\n };\n },\n }}\n />\n </div>\n )}\n </FilterItemContainer>,\n <DatePickerFilterItem label=\"日期\" name=\"date\" picker=\"week\" />,\n <TypeDateRangePickerFilterItem\n label=\"复杂日期范围\"\n name=\"type-data-range\"\n allowEmpty={[true, true]}\n />,\n <DateRangePickerFilterItem label=\"日期范围\" name=\"date-range\" />,\n <UserFilterItem\n label=\"用户选择\"\n name=\"user\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n {\n label: \"用户三\",\n value: 3,\n description: \"我是用户描述\",\n },\n ],\n };\n },\n }}\n />,\n <FunctionSelectFilterItem\n label=\"职能选择\"\n name=\"function\"\n onlyAllowLastLevel\n single\n />,\n <IndustrySelectFilterItem\n label=\"行业选择\"\n name=\"industry\"\n onlyAllowLastLevel\n />,\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n}]\n},{\n title: `树形筛选`,\n description: `展示 TreeFilterItem 树形选择组件的使用`,\n code: `const { default: Filter, TreeFilterItem } = _Filter;\nconst { default: treeData } = _data;\nconst { useState } = React;\nconst { Space } = antd;\n\nconst BaseExample = () => {\n const [filter, setFilter] = useState([]);\n const [filter2, setFilter2] = useState([]);\n\n return (\n <Space direction=\"vertical\">\n <Filter\n value={filter}\n onChange={setFilter}\n list={[\n [\n <TreeFilterItem\n name=\"tree\"\n single\n label=\"树组件\"\n fieldNames={{\n title: \"name\",\n key: \"id\",\n children: \"children\",\n }}\n api={{\n loader: () => {\n return treeData.children;\n },\n }}\n />,\n ],\n ]}\n />\n <Filter\n value={filter2}\n onChange={setFilter2}\n list={[\n [\n <TreeFilterItem\n name=\"tree\"\n label=\"树组件\"\n fieldNames={{\n title: \"name\",\n key: \"id\",\n children: \"children\",\n }}\n api={{\n loader: () => {\n return treeData.children;\n },\n }}\n />,\n ],\n ]}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_17\n},{\n name: \"_data\",\n packageName: \"@components/Filter/doc/mock/tree-data.json\",\n component: component_18\n}]\n},{\n title: `筛选值展示`,\n description: `展示 FilterValueDisplay、FilterItem、FilterLines、PopoverItem 等组件的独立使用`,\n code: `const {\n FilterValueDisplay,\n FilterItem,\n FilterLines,\n PopoverItem,\n InputFilterItem,\n CityFilterItem,\n AdvancedSelectFilterItem,\n UserFilterItem,\n FunctionSelectFilterItem,\n IndustrySelectFilterItem,\n} = _Filter;\nconst { Space, Input } = antd;\nconst { useState } = React;\nconst BaseExample = () => {\n const [value, setValue] = useState([\n {\n label: \"城市\",\n name: \"city\",\n value: [\n { label: \"上海\", value: \"010\" },\n { label: \"北京\", value: \"020\" },\n ],\n },\n {\n label: \"职能\",\n name: \"function\",\n value: [\n { label: \"产品经理\", value: \"010\" },\n { label: \"销售\", value: \"020\" },\n {\n label: \"客户经理\",\n value: \"030\",\n },\n ],\n },\n ]);\n return (\n <Space direction=\"vertical\">\n <FilterValueDisplay value={value} onChange={setValue} />\n <Space>\n <FilterItem label=\"客户\" />\n <FilterItem label=\"客户\" active />\n <FilterItem label=\"客户\" open />\n <FilterItem label=\"超长超长超长超长超长超长超长超长\" active open />\n </Space>\n <FilterLines\n list={[\n [\n <FilterItem label=\"客户\" />,\n <FilterItem label=\"职位\" />,\n <FilterItem label=\"职位负责人\" />,\n ],\n [\n <FilterItem label=\"开始时间\" />,\n <FilterItem label=\"结束时间\" />,\n <FilterItem label=\"职位BD人\" />,\n ],\n [\n <FilterItem label=\"开始时间\" />,\n <FilterItem label=\"结束时间\" />,\n <FilterItem label=\"职位BD人\" />,\n ],\n [\n <FilterItem label=\"开始时间\" />,\n <FilterItem label=\"结束时间\" />,\n <FilterItem label=\"职位BD人\" />,\n ],\n ]}\n />\n <PopoverItem label=\"客户\">\n {({ value, onChange }) => (\n <Input value={value} onChange={(e) => onChange(e.target.value)} />\n )}\n </PopoverItem>\n <FilterLines\n list={[\n [\n <InputFilterItem label=\"文字\" />,\n <CityFilterItem label=\"城市\" />,\n <AdvancedSelectFilterItem\n label=\"高级选择\"\n api={{\n loader: () => {\n return {\n pageData: [\n { label: \"第一项\", value: 1 },\n { label: \"第二项\", value: 2, disabled: true },\n {\n label: \"第三项\",\n value: 3,\n },\n ],\n };\n },\n }}\n />,\n <UserFilterItem\n label=\"用户选择\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n {\n label: \"用户三\",\n value: 3,\n description: \"我是用户描述\",\n },\n ],\n };\n },\n }}\n />,\n <FunctionSelectFilterItem label=\"职能选择\" />,\n <IndustrySelectFilterItem label=\"行业选择\" />,\n ],\n ]}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_17\n}]\n},{\n title: `数值范围筛选`,\n description: `展示 NumberRangeFilterItem 数值范围筛选组件的使用`,\n code: `const {\n default: Filter,\n NumberRangeFilterItem,\n getFilterValue,\n} = _Filter;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n\n return (\n <Filter\n value={value}\n onChange={(value) => {\n console.log('筛选值:', getFilterValue(value));\n onChange(value);\n }}\n list={[\n [\n <NumberRangeFilterItem label=\"年龄\" name=\"age\" unit=\"岁\" />,\n <NumberRangeFilterItem label=\"薪资\" name=\"salary\" unit=\"万\" />,\n <NumberRangeFilterItem label=\"工作经验\" name=\"experience\" unit=\"年\" />,\n ],\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n}]\n},{\n title: `级联筛选`,\n description: `展示 CascaderFilterItem 级联选择组件的使用`,\n code: `const {\n default: Filter, CascaderFilterItem, getFilterValue,\n} = _Filter;\nconst {useState} = React;\n\nconst options = [{\n label: '浙江', value: 'zhejiang', children: [{\n label: '杭州',\n value: 'hangzhou',\n children: [{label: '西湖区', value: 'xihu'}, {label: '滨江区', value: 'binjiang'}, {\n label: '余杭区', value: 'yuhang'\n },],\n }, {\n label: '宁波',\n value: 'ningbo',\n children: [{label: '海曙区', value: 'haishu'}, {label: '江北区', value: 'jiangbei'},],\n },],\n}, {\n label: '江苏', value: 'jiangsu', children: [{\n label: '南京',\n value: 'nanjing',\n children: [{label: '玄武区', value: 'xuanwu'}, {label: '秦淮区', value: 'qinhuai'},],\n }, {\n label: '苏州',\n value: 'suzhou',\n children: [{label: '姑苏区', value: 'gusu'}, {label: '吴中区', value: 'wuzhong'},],\n },],\n},];\n\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n\n return (<Filter\n value={value}\n onChange={(value) => {\n console.log('筛选值:', getFilterValue(value));\n onChange(value);\n }}\n list={[[<CascaderFilterItem\n label=\"地区选择\"\n name=\"region\"\n options={options}\n placeholder=\"请选择地区\"\n />,],]}\n />);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n}]\n},{\n title: `自定义筛选字段`,\n description: `展示如何使用 withFilterValue 将原生 Select 组件包装成筛选字段`,\n code: `const {\n default: Filter,\n InputFilterItem,\n CityFilterItem,\n withFilterValue,\n} = _Filter;\nconst { Select } = antd;\nconst { useState } = React;\n\n// 自定义下拉筛选组件 - 展示如何使用 withFilterValue 包装原生组件\nconst CustomSelectFilter = withFilterValue(({ label, value, onChange, options }) => {\n return (\n <Select\n placeholder={\\`请选择\\${label}\\`}\n value={value?.value}\n onChange={(val) => onChange({ label, value: val })}\n allowClear\n style={{ width: 200 }}\n options={options}\n />\n );\n});\n\nconst BaseExample = () => {\n const [value, onChange] = useState([]);\n\n return (\n <Filter\n value={value}\n onChange={(value) => {\n console.log('筛选值:', value);\n onChange(value);\n }}\n list={[\n [\n <InputFilterItem label=\"部门\" name=\"department\" placeholder=\"请输入部门名称\" />,\n <CityFilterItem label=\"城市\" name=\"city\" />,\n <CustomSelectFilter\n label=\"项目状态\"\n name=\"status\"\n options={[\n { label: '进行中', value: 'ongoing' },\n { label: '已完成', value: 'completed' },\n { label: '已暂停', value: 'paused' },\n { label: '已取消', value: 'cancelled' },\n ]}\n />,\n <CustomSelectFilter\n label=\"优先级\"\n name=\"priority\"\n options={[\n { label: '高', value: 'high' },\n { label: '中', value: 'medium' },\n { label: '低', value: 'low' },\n ]}\n />,\n ],\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_17\n}]\n},{\n title: `FilterProvider 和 useFilter`,\n description: `展示如何使用 FilterProvider 和 useFilter Hook 自定义筛选界面`,\n code: `const {\n FilterProvider,\n FilterLines,\n FilterValueDisplay,\n useFilter,\n InputFilterItem,\n CityFilterItem,\n UserFilterItem,\n FunctionSelectFilterItem,\n IndustrySelectFilterItem,\n DatePickerFilterItem,\n NumberRangeFilterItem,\n} = _Filter;\nconst { Space, Card, Button, Modal, Tag, Alert } = antd;\nconst { useState } = React;\n\n// 演示 FilterProvider 和 useFilter 的使用\nconst CustomFilterContent = () => {\n const { value, onChange } = useFilter();\n const [modalVisible, setModalVisible] = useState(false);\n\n const handleViewFilterValue = () => {\n setModalVisible(true);\n };\n\n const renderFilterValue = () => {\n if (!value) {\n return <p>暂无筛选条件</p>;\n }\n\n // 处理 value 可能是 Map 的情况\n const valueArray = value instanceof Map ? Array.from(value.values()) : (Array.isArray(value) ? value : []);\n\n if (valueArray.length === 0) {\n return <p>暂无筛选条件</p>;\n }\n\n return (\n <Space direction=\"vertical\" size={12}>\n {valueArray.map((item, index) => (\n <Tag key={index} color=\"blue\" style={{ fontSize: 14 }}>\n <strong>{item.label}</strong>: {Array.isArray(item.value)\n ? item.value.map(v => v.label).join(', ')\n : item.value?.label || item.value}\n </Tag>\n ))}\n </Space>\n );\n };\n\n return (\n <Space direction=\"vertical\" size={16} style={{ width: '100%' }}>\n <Alert\n message=\"使用提示\"\n description=\"点击筛选项,输入值后点击「确定」按钮,然后点击下方按钮查看筛选条件\"\n type=\"info\"\n showIcon\n />\n\n <Card title=\"筛选器\" size=\"small\">\n <FilterLines\n list={[\n [\n <InputFilterItem label=\"姓名\" name=\"name\" />,\n <CityFilterItem label=\"城市\" name=\"city\" />,\n <UserFilterItem label=\"用户\" name=\"user\" />,\n <FunctionSelectFilterItem label=\"职能\" name=\"function\" />,\n ],\n [\n <IndustrySelectFilterItem label=\"行业\" name=\"industry\" />,\n <DatePickerFilterItem label=\"创建时间\" name=\"createTime\" />,\n <NumberRangeFilterItem label=\"年龄\" name=\"age\" />,\n ],\n ]}\n />\n </Card>\n\n <Button type=\"primary\" onClick={handleViewFilterValue}>\n 查看筛选值\n </Button>\n\n <Modal\n title=\"当前筛选值\"\n open={modalVisible}\n onCancel={() => setModalVisible(false)}\n footer={[\n <Button key=\"close\" onClick={() => setModalVisible(false)}>\n 关闭\n </Button>,\n ]}\n width={600}\n >\n {renderFilterValue()}\n <div style={{ marginTop: 16 }}>\n <Button\n type=\"link\"\n size=\"small\"\n onClick={() => {\n navigator.clipboard.writeText(JSON.stringify(value, null, 2));\n }}\n >\n 复制 JSON 数据\n </Button>\n </div>\n </Modal>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n const [value, setValue] = useState([]);\n\n return (\n <FilterProvider value={value} onChange={setValue}>\n <CustomFilterContent />\n {value.length > 0 && (\n <FilterValueDisplay value={value} onChange={setValue} />\n )}\n </FilterProvider>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Filter\",\n packageName: \"@components/Filter\",\n component: component_15\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_17\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_31 from '@kne/flex-box';\nimport * as component_32 from 'antd';\nconst readmeConfig = {\n name: `flex-box`,\n summary: ``,\n \n \n api: `<h3>useFlexBox</h3>\n<p>const {ref, column} = useFlexBox(props);</p>\n<p>注意:返回的 ref 必须传给一个 dom 的 ref</p>\n<p>继承了<a href=\"https://ant.design/components/list-cn#list\">Ant Design List props</a>的参数,同时也新增了两个参数:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>columns</td>\n<td>实际用于 <code>List</code> 的 <code>grid</code></td>\n<td><code>columnProps[]</code></td>\n<td><code>defaultColumns</code></td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>设置 <code>column</code></td>\n<td>(column) => onChange()</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>columnProps</h4>\n<p>默认值:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>width</td>\n<td>视口宽度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>col</td>\n<td>列数</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>size</td>\n<td>根据 <code>col</code> 列数填每页数据加载多少条</td>\n<td>number</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<pre><code class=\"language-text\"> defaultColumns = [\n {width: 576, col: 1, size: 15},\n {width: 768, col: 2, size: 12},\n {width: 1200, col: 4, size: 12},\n {width: 1600, col: 5, size: 15}\n ]\n</code></pre>\n<h3>FlexBox</h3>\n<p>同 <code>useFlexBox</code> 参数</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>outerClassName</td>\n<td><code>FlexBox</code> 父元素的 <code>className</code></td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>gutter</td>\n<td>栅格间隔</td>\n<td>number</td>\n<td>16</td>\n</tr>\n</tbody>\n</table>\n<h4>FlexBox.Item</h4>\n<p>同 <a href=\"https://ant.design/components/list-cn#listitem\">Ant Design List.Item</a></p>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `这里填写示例标题`,\n description: `这里填写示例说明`,\n code: `const {default:FlexBox} = _FlexBox;\nconst { Card } = antd;\n\nconst BaseExample = () => {\n return (\n <FlexBox\n dataSource={[\n {\n title: \"Title 1\",\n },\n {\n title: \"Title 2\",\n },\n {\n title: \"Title 3\",\n },\n {\n title: \"Title 4\",\n },\n {\n title: \"Title 5\",\n },\n {\n title: \"Title 6\",\n },\n ]}\n renderItem={(item) => (\n <FlexBox.Item>\n <Card title={item.title}>Card content</Card>\n </FlexBox.Item>\n )}\n />\n );\n};\n\nrender(<BaseExample />);\n\n\n`,\n scope: [{\n name: \"_FlexBox\",\n packageName: \"@kne/flex-box\",\n component: component_31\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_32\n}]\n},{\n title: `这里填写示例标题`,\n description: `这里填写示例说明`,\n code: `const {FlexBoxFetch} = _FlexBox;\nconst {Card, Button} = antd;\nconst {useRef} = React;\nconst BaseExample = () => {\n const ref = useRef();\n return (<div>\n <FlexBoxFetch\n ref={ref}\n pagination={{ position: 'bottom', align: 'center' }}\n getFetchApi={({size}) => {\n return {\n data: {\n pageSize: size,\n }, loader: ({data}) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n pageData: Array.from({length: data.pageSize}).map((item, index) => {\n return {\n key: index, title: \\`第\\${index}项\\`,\n };\n }),\n });\n }, 1000);\n });\n },\n };\n }}\n renderItem={(item) => (<FlexBoxFetch.Item>\n <Card title={item.title}>Card content</Card>\n </FlexBoxFetch.Item>)}\n />\n <Button\n onClick={() => {\n console.log(ref.current);\n }}\n >\n 获取FetchApi\n </Button>\n </div>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_FlexBox\",\n packageName: \"@kne/flex-box\",\n component: component_31\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_32\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_40 from '@components/FormInfo';\nimport * as component_41 from '@components/Modal';\nimport * as component_42 from 'antd';\nimport * as component_43 from '@components/Global';\nimport * as component_44 from '@components/Content';\nimport * as component_45 from 'lodash';\nconst readmeConfig = {\n name: `FormInfo`,\n summary: `<p>功能强大的表单组件,提供完整的数据管理、校验和样式解决方案</p>\n<p>FormInfo 是一个全功能的表单解决方案,集成了数据录入、校验规则管理、样式布局等功能,适用于各种复杂场景的表单需求。</p>\n<h3>核心特性</h3>\n<p><strong>分层校验规则管理</strong></p>\n<ul>\n<li>支持默认级、preset 级、Form 级三层校验规则覆盖</li>\n<li>字符串形式规则调用,简洁直观(如 <code>REQ LEN-3-10 EMAIL</code>)</li>\n<li>支持异步校验规则,满足复杂业务场景需求</li>\n<li>规则参数化支持,灵活可配置</li>\n</ul>\n<p><strong>丰富的表单组件</strong></p>\n<ul>\n<li>提供基础组件:Input、TextArea、Select、DatePicker、RadioGroup、Checkbox、Switch 等</li>\n<li>提供业务组件:地址选择、行业选择、职能选择、用户选择、级联选择等</li>\n<li>提供高级组件:头像上传、文件上传、签名、薪资输入、电话号码输入、金额输入等</li>\n<li>所有组件统一封装,使用体验一致</li>\n</ul>\n<p><strong>灵活的布局方式</strong></p>\n<ul>\n<li>FormInfo 支持分组展示和分栏布局</li>\n<li>List 组件实现多段式列表表单,支持动态添加删除</li>\n<li>TableList 组件提供表格形式的列表展示</li>\n<li>支持无限嵌套,轻松实现复杂表单结构</li>\n</ul>\n<p><strong>多种表单形态</strong></p>\n<ul>\n<li>Form:基础表单组件</li>\n<li>FormModal:弹窗表单,配合 Modal 使用</li>\n<li>FormDrawer:抽屉表单,配合 Drawer 使用</li>\n<li>FormStepModal:分步表单,支持多步骤数据收集</li>\n<li>提供 useFormModal、useFormDrawer、useFormStepModal Hooks</li>\n</ul>\n<p><strong>事件驱动架构</strong></p>\n<ul>\n<li>完善的事件机制,支持表单生命周期监听</li>\n<li>可监听字段添加、删除、校验、值变化等事件</li>\n<li>便于扩展和集成自定义逻辑</li>\n</ul>\n<p><strong>拦截器支持</strong></p>\n<ul>\n<li>支持字段值拦截器</li>\n<li>可实现 Field 值和 Form Data 之间的转换</li>\n<li>解决日期格式化、数据映射等常见问题</li>\n</ul>\n<h3>适用场景</h3>\n<p><strong>数据采集场景</strong></p>\n<ul>\n<li>用户注册、信息录入、问卷调查等基础表单</li>\n<li>个人资料编辑、设置修改等表单场景</li>\n</ul>\n<p><strong>业务流程场景</strong></p>\n<ul>\n<li>审批流程中的信息填写</li>\n<li>订单创建、项目立项等复杂表单</li>\n<li>多步骤向导式数据收集</li>\n</ul>\n<p><strong>数据管理场景</strong></p>\n<ul>\n<li>列表数据的批量编辑</li>\n<li>动态列表的增删改查</li>\n<li>复杂嵌套数据结构的录入</li>\n</ul>\n<p><strong>集成场景</strong></p>\n<ul>\n<li>配合弹窗、抽屉组件的表单展示</li>\n<li>与数据加载组件结合的表单编辑</li>\n<li>自定义业务组件的表单集成</li>\n</ul>\n<h3>技术亮点</h3>\n<p><strong>上下文与 Ref 双重 API</strong></p>\n<ul>\n<li>提供 useFormContext Hook 在组件内获取表单实例</li>\n<li>支持 ref 方式在外部访问表单方法</li>\n<li>灵活的表单操作方式</li>\n</ul>\n<p><strong>多语言支持</strong></p>\n<ul>\n<li>内置国际化支持</li>\n<li>可自定义多语言配置</li>\n<li>支持字段级别的语言切换</li>\n</ul>\n<p><strong>类型安全</strong></p>\n<ul>\n<li>完善的 TypeScript 类型定义</li>\n<li>编译时类型检查</li>\n<li>良好的开发体验</li>\n</ul>\n<p><strong>高度可扩展</strong></p>\n<ul>\n<li>Field 组件实现规范清晰</li>\n<li>支持自定义 Field 组件</li>\n<li>选择器组件统一封装模式</li>\n</ul>\n<p><strong>性能优化</strong></p>\n<ul>\n<li>按需加载组件</li>\n<li>优化的重渲染机制</li>\n<li>支持大规模表单场景</li>\n</ul>`,\n \n \n api: `<h3>Form</h3>\n<p>表单核心组件,提供数据域管理、校验规则、事件驱动等功能。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>data</td>\n<td>表单初始数据</td>\n<td>object</td>\n<td>否</td>\n<td>{}</td>\n</tr>\n<tr>\n<td>rules</td>\n<td>自定义校验规则,key为规则名,value为校验函数</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>interceptors</td>\n<td>自定义拦截器配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onSubmit</td>\n<td>表单提交成功的回调,接收表单数据</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onError</td>\n<td>表单校验失败的回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onPrevSubmit</td>\n<td>提交前回调,校验前触发</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>debug</td>\n<td>是否开启调试模式,打印表单状态</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>noFilter</td>\n<td>是否禁用数据过滤</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>helperGuideName</td>\n<td>帮助指引配置名称</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>lang</td>\n<td>语言配置,支持多语言</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FormInfo</h3>\n<p>表单信息分组组件,用于组织和管理表单字段的布局。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>分组标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>list</td>\n<td>字段数组</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>column</td>\n<td>分栏数量,响应式布局</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>gap</td>\n<td>字段间距</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>extra</td>\n<td>额外内容,显示在标题右侧</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>List</h3>\n<p>多段式列表表单组件,支持动态添加和删除表单项。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名,对应表单数据中的 key</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>列表标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>list</td>\n<td>字段数组</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大数量,达到后隐藏添加按钮</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>minLength</td>\n<td>最小数量,达到后隐藏删除按钮</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n</tr>\n<tr>\n<td>addText</td>\n<td>添加按钮文本</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>itemTitle</td>\n<td>单项标题,可以是字符串或函数</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>important</td>\n<td>是否标记为重要项,样式区分</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>block</td>\n<td>是否占满一行</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>outer</td>\n<td>外层容器组件</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>Outer</td>\n</tr>\n<tr>\n<td>renderChildren</td>\n<td>子项渲染函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>deleteButtonProps</td>\n<td>删除按钮属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TableList</h3>\n<p>表格形式的列表表单组件,继承自 List,提供表格展示方式。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>列表标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>list</td>\n<td>字段数组</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>最大数量</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>minLength</td>\n<td>最小数量</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n</tr>\n<tr>\n<td>isUnshift</td>\n<td>新增项是否添加到开头</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n</tbody>\n</table>\n<h3>FormModal</h3>\n<p>弹窗表单组件,将 Form 和 Modal 组合使用。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>open</td>\n<td>是否显示弹窗</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>弹窗标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClose</td>\n<td>关闭回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>formProps</td>\n<td>Form 组件属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>表单内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>底部按钮配置</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>width</td>\n<td>弹窗宽度</td>\n<td>string</td>\n<td>否</td>\n<td>520</td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>装饰器函数,用于包装表单内容</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FormDrawer</h3>\n<p>抽屉表单组件,将 Form 和 Drawer 组合使用。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>open</td>\n<td>是否显示抽屉</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>抽屉标题</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClose</td>\n<td>关闭回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>formProps</td>\n<td>Form 组件属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>表单内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>底部按钮配置</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>width</td>\n<td>抽屉宽度</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>装饰器函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FormStepModal</h3>\n<p>分步表单弹窗组件,支持多步骤数据收集。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>open</td>\n<td>是否显示弹窗</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items</td>\n<td>步骤配置数组</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClose</td>\n<td>关闭回调</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>底部按钮配置</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>装饰器函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>autoClose</td>\n<td>最后一步完成后是否自动关闭</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>cancelText</td>\n<td>取消按钮文本</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>completeText</td>\n<td>完成按钮文本</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>nextText</td>\n<td>下一步按钮文本</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>items 配置说明</h4>\n<p>items 数组中每个元素为步骤配置对象:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>步骤标题</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>formProps</td>\n<td>Form 组件属性,可以是对象或函数</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>步骤底部按钮配置</td>\n<td>array</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>useFormModal</h3>\n<p>获取表单弹窗 Hook,返回一个可调用函数来弹出表单弹窗。</p>\n<h4>返回值</h4>\n<p>返回一个函数,调用该函数弹出 FormModal 弹窗,参数同 FormModal 组件属性。</p>\n<h3>useFormDrawer</h3>\n<p>获取表单抽屉 Hook,返回一个可调用函数来弹出表单抽屉。</p>\n<h4>返回值</h4>\n<p>返回一个函数,调用该函数弹出 FormDrawer 抽屉,参数同 FormDrawer 组件属性。</p>\n<h3>useFormStepModal</h3>\n<p>获取分步表单弹窗 Hook,返回一个可调用函数来弹出分步表单弹窗。</p>\n<h4>返回值</h4>\n<p>返回一个函数,调用该函数弹出 FormStepModal 弹窗,参数同 FormStepModal 组件属性。</p>\n<h3>FormModalButton</h3>\n<p>按钮触发表单弹窗组件,支持加载数据后弹出。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>数据加载配置,参考 @kne/react-fetch</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>FormModal 弹窗属性,可以是对象或函数</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>modalProps 函数形式参数</h4>\n<p>当 modalProps 为函数时,接收以下参数:</p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>data</td>\n<td>加载的数据</td>\n<td>any</td>\n</tr>\n<tr>\n<td>fetchApi</td>\n<td>fetch 实例</td>\n<td>object</td>\n</tr>\n<tr>\n<td>close</td>\n<td>关闭弹窗方法</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>FormStepModalButton</h3>\n<p>按钮触发的分步表单弹窗组件。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>数据加载配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>FormStepModal 弹窗属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FormDrawerButton</h3>\n<p>按钮触发的表单抽屉组件。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>数据加载配置</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>drawerProps</td>\n<td>FormDrawer 抽屉属性</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>SubmitButton</h3>\n<p>提交按钮组件,点击后触发表单校验和提交。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>autoClose</td>\n<td>提交成功后是否自动关闭弹窗</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>CancelButton</h3>\n<p>取消按钮组件,点击后重置表单或关闭弹窗。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FormApiButton</h3>\n<p>表单 API 按钮组件,可执行表单操作。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>onClick</td>\n<td>点击回调,接收表单 API 对象</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>autoClose</td>\n<td>点击后是否自动关闭弹窗</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n</tr>\n<tr>\n<td>children</td>\n<td>按钮内容</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>onClick 回调参数</h4>\n<p>onClick 回调接收包含表单操作 API 的对象:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>openApi</td>\n<td>表单 API 对象</td>\n<td>object</td>\n</tr>\n<tr>\n<td>submit</td>\n<td>触发表单提交方法</td>\n<td>function</td>\n</tr>\n<tr>\n<td>reset</td>\n<td>重置表单方法</td>\n<td>function</td>\n</tr>\n<tr>\n<td>validate</td>\n<td>校验表单方法</td>\n<td>function</td>\n</tr>\n<tr>\n<td>setFields</td>\n<td>设置字段值方法</td>\n<td>function</td>\n</tr>\n<tr>\n<td>getFields</td>\n<td>获取字段值方法</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>useFormContext</h3>\n<p>表单上下文 Hook,在 Form 内部获取表单实例和方法。</p>\n<h4>返回值</h4>\n<p>返回表单 API 对象,包含以下属性和方法:</p>\n<table>\n<thead>\n<tr>\n<th>属性名/方法名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>openApi</td>\n<td>表单 API 对象</td>\n<td>object</td>\n</tr>\n<tr>\n<td>formData</td>\n<td>表单数据</td>\n<td>object</td>\n</tr>\n</tbody>\n</table>\n<p>openApi 包含以下方法:</p>\n<table>\n<thead>\n<tr>\n<th>方法名</th>\n<th>说明</th>\n<th>参数</th>\n<th>返回值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>submit</td>\n<td>提交表单</td>\n<td>-</td>\n<td>Promise</td>\n</tr>\n<tr>\n<td>reset</td>\n<td>重置表单</td>\n<td>-</td>\n<td>void</td>\n</tr>\n<tr>\n<td>validate</td>\n<td>校验表单</td>\n<td>-</td>\n<td>Promise</td>\n</tr>\n<tr>\n<td>setFields</td>\n<td>设置字段值</td>\n<td>fields: array, options: object</td>\n<td>void</td>\n</tr>\n<tr>\n<td>getFields</td>\n<td>获取字段值</td>\n<td>names: array</td>\n<td>object</td>\n</tr>\n</tbody>\n</table>\n<h3>MultiField</h3>\n<p>多字段组件,支持在单个 Field 中包含多个子字段。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>子字段组件</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>ErrorTip</h3>\n<p>错误提示组件,可自定义字段错误信息的展示方式。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>errorRender</td>\n<td>自定义错误渲染函数</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>字段组件</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>errorRender 回调参数</h4>\n<p>errorRender 回调接收以下参数:</p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>validateData</td>\n<td>字段校验数据</td>\n<td>object</td>\n</tr>\n<tr>\n<td>hasError</td>\n<td>是否有错误</td>\n<td>boolean</td>\n</tr>\n<tr>\n<td>errorMsg</td>\n<td>错误信息</td>\n<td>string</td>\n</tr>\n</tbody>\n</table>\n<h3>FormItem</h3>\n<p>表单项容器组件,用于包装表单字段。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>tips</td>\n<td>提示信息</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>labelHidden</td>\n<td>是否隐藏标签</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>children</td>\n<td>字段组件</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>Field 类型:基础组件</h3>\n<p>以下为基础表单字段组件,请参考 antd 文档:</p>\n<p><strong>Input</strong> - 文本输入框</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>占位符</td>\n<td>string</td>\n<td>否</td>\n<td>请输入{label}</td>\n</tr>\n<tr>\n<td>tips</td>\n<td>提示信息,显示问号图标</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>TextArea</strong> - 多行文本输入框</p>\n<p><strong>InputNumber</strong> - 数字输入框</p>\n<p><strong>Select</strong> - 下拉选择框</p>\n<p><strong>DatePicker</strong> - 日期选择器</p>\n<ul>\n<li>DatePicker.MonthPicker</li>\n<li>DatePicker.RangePicker</li>\n<li>DatePicker.WeekPicker</li>\n</ul>\n<p><strong>TimePicker</strong> - 时间选择器</p>\n<ul>\n<li>TimePicker.RangePicker</li>\n</ul>\n<p><strong>RadioGroup</strong> - 单选按钮组</p>\n<p><strong>Checkbox</strong> - 复选框</p>\n<p><strong>CheckboxGroup</strong> - 复选框组</p>\n<p><strong>Switch</strong> - 开关</p>\n<p><strong>Rate</strong> - 评分</p>\n<p><strong>Slider</strong> - 滑块</p>\n<p><strong>TreeSelect</strong> - 树选择</p>\n<h3>Field 类型:业务组件</h3>\n<p><strong>AddressSelect</strong> - 地址选择组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否使用弹窗形式</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>FunctionSelect</strong> - 职能选择组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>IndustrySelect</strong> - 行业选择组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Cascader</strong> - 级联选择组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>options</td>\n<td>选项数据</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Avatar</strong> - 头像上传组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>border</td>\n<td>裁剪边框</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>width</td>\n<td>宽度</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>height</td>\n<td>高度</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>dropModalSize</td>\n<td>弹窗尺寸</td>\n<td>string</td>\n<td>否</td>\n<td>small</td>\n</tr>\n<tr>\n<td>block</td>\n<td>是否占满一行</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>PhoneNumber</strong> - 电话号码输入组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>MoneyInput</strong> - 金额输入组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>SalaryInput</strong> - 薪资范围输入组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Upload</strong> - 文件上传组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maxCount</td>\n<td>最大上传数量</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>block</td>\n<td>是否占满一行</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>ColorPicker</strong> - 颜色选择器</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Signature</strong> - 签名组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>Field 类型:高级选择组件</h3>\n<p><strong>AdvancedSelect</strong> - 高级选择组件,支持列表和表格两种形态</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>数据加载 API 配置</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n<tr>\n<td>isPopup</td>\n<td>是否使用弹窗形式</td>\n<td>boolean</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>getSearchProps</td>\n<td>搜索框配置</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h4>api 配置说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>params</td>\n<td>加载参数</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>SuperSelect</strong> - 超级选择组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>api</td>\n<td>数据加载 API 配置</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>single</td>\n<td>是否单选</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p><strong>SuperSelectTableList</strong> - 表格列表选择组件</p>\n<p><strong>SuperSelectUser</strong> - 用户选择组件</p>\n<p><strong>SuperSelectTree</strong> - 树选择组件</p>\n<h3>Field 类型:特殊组件</h3>\n<p><strong>TypeDateRangePicker</strong> - 类型日期范围选择器</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p><strong>DatePickerToday</strong> - 至今日期选择器</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>字段名</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>字段标签</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rule</td>\n<td>校验规则</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n</tr>\n<tr>\n<td>soFarText</td>\n<td>至今文本</td>\n<td>string</td>\n<td>否</td>\n<td>至今</td>\n</tr>\n</tbody>\n</table>\n<h3>fieldDecorator</h3>\n<p>字段装饰器工具,用于创建自定义 Field 组件。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>createWithFieldDecorator</td>\n<td>创建带装饰器的字段组件</td>\n<td>function</td>\n</tr>\n<tr>\n<td>withInputDefaultPlaceholder</td>\n<td>添加输入框默认占位符</td>\n<td>function</td>\n</tr>\n<tr>\n<td>withSelectDefaultPlaceholder</td>\n<td>添加选择器默认占位符</td>\n<td>function</td>\n</tr>\n<tr>\n<td>withLang</td>\n<td>添加多语言支持</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>hooks</h3>\n<p>表单相关 Hooks 集合。</p>\n<h4>常用 Hooks</h4>\n<table>\n<thead>\n<tr>\n<th>Hook 名</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>useField</td>\n<td>获取字段 API</td>\n</tr>\n<tr>\n<td>useReset</td>\n<td>获取重置方法</td>\n</tr>\n<tr>\n<td>useSubmit</td>\n<td>获取提交方法</td>\n</tr>\n</tbody>\n</table>\n<h3>widget</h3>\n<p>表单组件工具集。</p>\n<h3>utils</h3>\n<p>表单工具函数集。</p>\n<h3>formUtils</h3>\n<p>表单实用工具集。</p>\n<h3>RULES</h3>\n<p>内置校验规则。</p>\n<h4>常用规则</h4>\n<table>\n<thead>\n<tr>\n<th>规则名</th>\n<th>说明</th>\n<th>参数</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>REQ</td>\n<td>必填</td>\n<td>-</td>\n</tr>\n<tr>\n<td>LEN</td>\n<td>长度限制</td>\n<td>MIN-MAX</td>\n</tr>\n<tr>\n<td>EMAIL</td>\n<td>邮箱格式</td>\n<td>-</td>\n</tr>\n<tr>\n<td>TEL</td>\n<td>电话号码</td>\n<td>-</td>\n</tr>\n<tr>\n<td>NUM</td>\n<td>数字</td>\n<td>-</td>\n</tr>\n<tr>\n<td>INT</td>\n<td>整数</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>interceptors</h3>\n<p>内置拦截器。</p>\n<h4>使用方式</h4>\n<pre><code class=\"language-javascript\">// 注册拦截器\ninterceptors.input.use(\"date-string\", (value) => {\n return value ? new Date(value) : null;\n});\n\ninterceptors.output.use(\"date-string\", (value) => {\n return value ? dayjs(value).format(\"YYYY-MM-DD\") : \"\";\n});\n\n// 在字段中使用\n<Input name=\"date\" label=\"日期\" interceptor=\"date-string\"/>\n</code></pre>\n<h3>SelectInnerInput</h3>\n<p>选择器内部输入框组件,用于自定义选择器开发。</p>\n<h3>FormSteps</h3>\n<p>表单步骤组件,用于 FormStepModal 中显示步骤条。</p>\n<h3>formModule</h3>\n<p>表单模块,导出所有表单相关的组件和工具。</p>`,\n example: {\n isFull: true,\n className: `FormInfo_f344c`,\n style: `.FormInfo_f344c .input > .ant-row > .ant-col {\n padding: 10px 0;\n}\n.FormInfo_f344c .input .ant-space-item:last-child {\n width: 100%;\n}`,\n list: [{\n title: `基础表单`,\n description: `最简单的表单示例,包含常用的输入框、日期选择、下拉选择等基础字段,适合快速上手`,\n code: `const { default: FormInfo, Form, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space } = antd;\n\nconst { Input, TextArea, DatePicker, Select } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"客户信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"客户基本信息\"\n list={[\n <Input name=\"name\" label=\"客户姓名\" rule=\"REQ\" />,\n <Input name=\"phone\" label=\"联系电话\" rule=\"REQ PHONE\" />,\n <Input name=\"email\" label=\"电子邮箱\" rule=\"EMAIL\" />,\n <DatePicker name=\"birthday\" label=\"出生日期\" />,\n <Select\n name=\"gender\"\n label=\"性别\"\n rule=\"REQ\"\n options={[\n { label: \"男\", value: \"male\" },\n { label: \"女\", value: \"female\" },\n ]}\n />,\n <TextArea name=\"remark\" label=\"备注说明\" />,\n ]}\n />\n <SubmitButton type=\"primary\">保存客户信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `字段类型`,\n description: `展示FormInfo支持的各种字段类型,包括输入类、选择类、以及其他特殊字段类型`,\n code: `const { default: FormInfo, Form, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space, Divider } = antd;\n\nconst {\n Input,\n TextArea,\n InputNumber,\n DatePicker,\n DateRangePicker,\n Select,\n Switch,\n Rate,\n Slider,\n MoneyInput,\n ColorPicker,\n} = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"供应商信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={24}>\n <FormInfo\n title=\"基本资料\"\n list={[\n <Input name=\"companyName\" label=\"供应商名称\" rule=\"REQ LEN-3-50\" />,\n <TextArea name=\"description\" label=\"公司简介\" maxLength={500} />,\n <InputNumber name=\"creditScore\" label=\"信用评分\" min={0} max={100} />,\n <MoneyInput name=\"annualRevenue\" label=\"年营业额\" />,\n ]}\n />\n\n <Divider />\n\n <FormInfo\n title=\"合作信息\"\n list={[\n <DatePicker name=\"cooperateDate\" label=\"合作起始日期\" />,\n <DateRangePicker name=\"contractPeriod\" label=\"合同有效期\" />,\n <Select\n name=\"cooperateType\"\n label=\"合作类型\"\n rule=\"REQ\"\n options={[\n { label: \"独家代理\", value: \"exclusive\" },\n { label: \"一般代理\", value: \"normal\" },\n { label: \"战略合作伙伴\", value: \"strategic\" },\n ]}\n />,\n <Select\n name=\"productCategory\"\n label=\"供应产品类别\"\n mode=\"multiple\"\n options={[\n { label: \"电子元器件\", value: \"electronics\" },\n { label: \"机械配件\", value: \"machinery\" },\n { label: \"原材料\", value: \"materials\" },\n { label: \"包装材料\", value: \"packaging\" },\n ]}\n />,\n ]}\n />\n\n <Divider />\n\n <FormInfo\n title=\"其他配置\"\n list={[\n <Switch name=\"isPreferred\" label=\"是否优先供应商\" />,\n <Rate name=\"qualityRating\" label=\"质量评级\" />,\n <Slider name=\"deliveryScore\" label=\"交付及时性评分\" />,\n <ColorPicker name=\"brandColor\" label=\"品牌标识色\" />,\n ]}\n />\n\n <SubmitButton type=\"primary\">提交供应商信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `表单校验`,\n description: `展示表单的校验规则使用,包括内置规则和自定义规则,以及异步校验和错误提示`,\n code: `const { default: FormInfo, Form, SubmitButton, ErrorTip, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space, Alert } = antd;\n\nconst { Input, Password } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n rules={{\n USERNAME: (value) => {\n // 自定义规则:用户名必须是字母开头,4-16位\n const pattern = /^[a-zA-Z][a-zA-Z0-9]{3,15}\\$/;\n return {\n result: pattern.test(value),\n errMsg: \"用户名必须以字母开头,4-16位字母或数字\",\n };\n },\n PASSWORD_STRENGTH: (value) => {\n // 自定义规则:密码强度校验\n const hasLetter = /[a-zA-Z]/.test(value);\n const hasNumber = /[0-9]/.test(value);\n const hasSpecial = /[!@#\\$%^&*]/.test(value);\n if (!hasLetter || !hasNumber || !hasSpecial) {\n return {\n result: false,\n errMsg: \"密码必须包含字母、数字和特殊字符\",\n };\n }\n return { result: true, errMsg: \"\" };\n },\n USERNAME_EXISTS: (value) => {\n // 异步校验:检查用户名是否已存在\n return new Promise((resolve) => {\n setTimeout(() => {\n const exists = [\"admin\", \"wangming\", \"zhangwei\"].includes(value);\n resolve({\n result: !exists,\n errMsg: exists ? \"该用户名已被占用\" : \"\",\n });\n }, 500);\n });\n },\n }}\n onSubmit={(data) => {\n modal({\n title: \"管理员账号创建成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <Alert\n message=\"账号注册规范\"\n description=\"REQ-必填 | LEN-最小-最大 | EMAIL-邮箱 | PHONE-手机号 | URL-网址 | USERNAME-自定义规则\"\n type=\"info\"\n />\n\n <FormInfo\n title=\"管理员账号信息\"\n list={[\n <ErrorTip name=\"username\">\n <Input\n name=\"username\"\n label=\"用户名\"\n rule=\"REQ LEN-4-16 USERNAME USERNAME_EXISTS\"\n tips=\"4-16位字母或数字,以字母开头(admin、wangming、zhangwei已被占用)\"\n />\n </ErrorTip>,\n <Password\n name=\"password\"\n label=\"登录密码\"\n rule=\"REQ LEN-8-20 PASSWORD_STRENGTH\"\n tips=\"至少8位,包含字母、数字和特殊字符\"\n />,\n <Password\n name=\"confirmPassword\"\n label=\"确认密码\"\n rule=\"REQ\"\n tips=\"请再次输入密码\"\n />,\n <Input name=\"email\" label=\"工作邮箱\" rule=\"REQ EMAIL\" />,\n <Input name=\"phone\" label=\"联系电话\" rule=\"REQ PHONE\" />,\n ]}\n />\n <SubmitButton type=\"primary\">创建管理员账号</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `多行字段`,\n description: `展示MultiField的使用,可以将多个字段在一行中横向排列`,\n code: `const { default: FormInfo, Form, MultiField, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\n\nconst { Input, TextArea, DatePicker } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"采购订单信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <FormInfo\n list={[\n <MultiField\n name=\"purchaseOrderNo\"\n label=\"采购单号\"\n rule=\"REQ\"\n field={Input}\n maxLength={20}\n />,\n <MultiField name=\"productName\" label=\"采购产品\" field={Input} />,\n <MultiField name=\"quantity\" label=\"采购数量\" field={Input} type=\"number\" />,\n <MultiField name=\"unitPrice\" label=\"单价\" field={Input} type=\"number\" />,\n <MultiField name=\"deliveryDate\" label=\"交付日期\" field={DatePicker} />,\n <MultiField name=\"note\" label=\"备注说明\" field={TextArea} />,\n ]}\n />\n <SubmitButton type=\"primary\">提交采购订单</SubmitButton>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n}]\n},{\n title: `业务字段`,\n description: `展示FormInfo提供的业务字段组件,如手机号、职能选择、行业选择、地址选择等`,\n code: `const { default: FormInfo, Form, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { PureGlobal } = global;\nconst { Space } = antd;\n\nconst {\n PhoneNumber,\n FunctionSelect,\n IndustrySelect,\n AddressSelect,\n SuperSelectUser,\n Avatar,\n Upload,\n SalaryInput,\n Input,\n} = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"候选人信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"候选人基本信息\"\n list={[\n <Avatar name=\"avatar\" label=\"头像照片\" />,\n <SuperSelectUser name=\"userId\" label=\"内部推荐人\" rule=\"REQ\" />,\n <PhoneNumber name=\"phone\" label=\"联系电话\" rule=\"REQ\" />,\n <Input name=\"email\" label=\"电子邮箱\" rule=\"EMAIL\" />,\n ]}\n />\n\n <FormInfo\n title=\"职业发展信息\"\n list={[\n <FunctionSelect name=\"function\" label=\"职能领域\" rule=\"REQ\" />,\n <IndustrySelect name=\"industry\" label=\"所属行业\" rule=\"REQ\" />,\n <SalaryInput\n name=\"salaryRange\"\n label=\"期望薪资范围\"\n rule=\"REQ\"\n showMonth\n remindUnit\n />,\n ]}\n />\n\n <FormInfo\n title=\"其他补充信息\"\n list={[\n <AddressSelect name=\"address\" label=\"工作地址\" level={3} />,\n <Upload name=\"resume\" label=\"简历附件\" block />,\n ]}\n />\n\n <SubmitButton type=\"primary\">提交候选人信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(\n <PureGlobal>\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `高级选择组件`,\n description: `展示AdvancedSelect高级选择组件的使用,支持从API加载数据、自定义列配置、多选等功能`,\n code: `const { default: FormInfo, Form, SubmitButton, AdvancedSelect, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space } = antd;\n\nconst { Input, TextArea } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"培训计划配置成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"课程选择\"\n list={[\n <AdvancedSelect\n name=\"trainingCourses\"\n label=\"选择培训课程\"\n rule=\"REQ\"\n mode=\"multiple\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n id: 1,\n name: \"前端架构设计最佳实践\",\n category: \"前端技术\",\n duration: 12,\n description: \"深入学习企业级前端架构设计方法\",\n },\n {\n id: 2,\n name: \"微服务架构设计与实现\",\n category: \"后端技术\",\n duration: 16,\n description: \"掌握微服务架构的核心设计模式\",\n },\n {\n id: 3,\n name: \"云原生应用开发\",\n category: \"云原生\",\n duration: 20,\n description: \"基于Kubernetes的云原生应用开发\",\n },\n {\n id: 4,\n name: \"大数据处理与分析\",\n category: \"数据技术\",\n duration: 18,\n description: \"Hadoop/Spark大数据处理技术\",\n },\n {\n id: 5,\n name: \"AI与机器学习实战\",\n category: \"人工智能\",\n duration: 24,\n description: \"深度学习模型训练与部署\",\n },\n ],\n };\n },\n }}\n columns={[\n { title: \"课程名称\", key: \"name\" },\n { title: \"技术方向\", key: \"category\" },\n { title: \"课时\", key: \"duration\" },\n ]}\n nameKey=\"id\"\n labelKey=\"name\"\n />,\n ]}\n />\n\n <FormInfo\n title=\"培训计划详情\"\n list={[\n <Input name=\"trainingObjective\" label=\"培训目标\" />,\n <TextArea name=\"trainingRequirements\" label=\"培训要求与说明\" block />,\n ]}\n />\n\n <SubmitButton type=\"primary\">提交培训计划</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `列表字段`,\n description: `展示List和TableList多段式列表字段的使用,支持动态添加、删除、最大长度限制等功能`,\n code: `const { default: FormInfo, Form, List, TableList, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space } = antd;\n\nconst { Input, DatePicker, TextArea } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"企业信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"企业基本信息\"\n list={[\n <Input name=\"companyName\" label=\"企业名称\" rule=\"REQ\" />,\n <TextArea name=\"companyDescription\" label=\"企业简介\" block />,\n ]}\n />\n\n <List\n name=\"productLines\"\n title=\"产品线列表\"\n itemTitle={({ index }) => \\`产品线 \\${index + 1}\\`}\n maxLength={10}\n list={[\n <Input name=\"lineName\" label=\"产品线名称\" rule=\"REQ\" />,\n <Input name=\"annualSales\" label=\"年销售额(万元)\" rule=\"REQ\" />,\n <TextArea name=\"lineFeatures\" label=\"产品线特点\" block />,\n ]}\n />\n\n <TableList\n name=\"partnerContacts\"\n title=\"合作伙伴联系人\"\n maxLength={5}\n list={[\n <Input name=\"contactName\" label=\"联系人姓名\" rule=\"REQ\" />,\n <DatePicker name=\"cooperateDate\" label=\"合作起始日期\" />,\n <Input name=\"contactPhone\" label=\"联系电话\" rule=\"REQ\" />,\n ]}\n />\n\n <SubmitButton type=\"primary\">提交企业信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `嵌套列表`,\n description: `展示在List中嵌套TableList的使用场景,实现更复杂的多层级数据结构`,\n code: `const { default: FormInfo, Form, List, TableList, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space } = antd;\n\nconst { Input, DatePicker, TextArea, Select } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"研发项目信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"项目基本信息\"\n list={[\n <Input name=\"projectName\" label=\"项目名称\" rule=\"REQ\" />,\n <TextArea name=\"projectDescription\" label=\"项目描述\" block />,\n ]}\n />\n\n <List\n name=\"releaseMilestones\"\n title=\"发布里程碑\"\n itemTitle={({ index }) => \\`里程碑 \\${index + 1}\\`}\n maxLength={5}\n important\n list={[\n <Input name=\"milestoneName\" label=\"里程碑名称\" rule=\"REQ\" />,\n <DatePicker name=\"releaseDate\" label=\"发布日期\" rule=\"REQ\" />,\n <TableList\n name=\"deliverables\"\n title=\"交付物清单\"\n maxLength={10}\n block\n list={[\n <Input name=\"deliverableName\" label=\"交付物名称\" rule=\"REQ\" />,\n <Select\n name=\"deliverableType\"\n label=\"交付物类型\"\n rule=\"REQ\"\n options={[\n { label: \"源代码\", value: \"code\" },\n { label: \"文档\", value: \"doc\" },\n { label: \"测试用例\", value: \"test\" },\n ]}\n />,\n ]}\n />,\n ]}\n />\n\n <SubmitButton type=\"primary\">提交项目信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `动态字段`,\n description: `展示根据选择值动态显示/隐藏字段的使用场景,实现字段联动效果`,\n code: `const { default: FormInfo, Form, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space, Alert } = antd;\nconst { useState } = React;\n\nconst { Input, Select, TextArea } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n const [employmentType, setEmploymentType] = useState(\"fulltime\");\n\n return (\n <Form\n onSubmit={(data) => {\n modal({\n title: \"人才录用信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <Alert\n message=\"动态字段展示\"\n description=\"根据录用类型显示不同的字段信息,实现字段联动效果\"\n type=\"info\"\n />\n\n <FormInfo\n title=\"候选人基本信息\"\n list={[\n <Input name=\"candidateName\" label=\"候选人姓名\" rule=\"REQ\" />,\n <Select\n name=\"employmentType\"\n label=\"录用类型\"\n rule=\"REQ\"\n onChange={(value) => {\n setEmploymentType(value);\n }}\n options={[\n { label: \"全职员工\", value: \"fulltime\" },\n { label: \"兼职顾问\", value: \"parttime\" },\n { label: \"外包合同\", value: \"contract\" },\n ]}\n />,\n ]}\n />\n\n {employmentType === \"fulltime\" && (\n <FormInfo\n title=\"全职员工信息\"\n list={[\n <Input name=\"employeeId\" label=\"员工工号\" rule=\"REQ\" />,\n <Input name=\"monthlySalary\" label=\"月薪(元)\" rule=\"REQ\" />,\n <Input name=\"socialSecurityNo\" label=\"社保账号\" />,\n <Select\n name=\"benefitLevel\"\n label=\"福利等级\"\n options={[\n { label: \"基础福利\", value: \"basic\" },\n { label: \"标准福利\", value: \"standard\" },\n { label: \"优厚福利\", value: \"premium\" },\n ]}\n />,\n ]}\n />\n )}\n\n {employmentType === \"parttime\" && (\n <FormInfo\n title=\"兼职顾问信息\"\n list={[\n <Input name=\"hourlyRate\" label=\"时薪(元/小时)\" rule=\"REQ\" />,\n <Input name=\"maxMonthlyHours\" label=\"最大月工时\" rule=\"REQ\" />,\n <TextArea name=\"serviceScope\" label=\"服务范围\" block />,\n ]}\n />\n )}\n\n {employmentType === \"contract\" && (\n <FormInfo\n title=\"外包合同信息\"\n list={[\n <Input name=\"contractPeriod\" label=\"合同期限\" rule=\"REQ\" />,\n <Input name=\"projectFee\" label=\"项目费用(元)\" rule=\"REQ\" />,\n <Select\n name=\"paymentTerm\"\n label=\"付款方式\"\n options={[\n { label: \"一次性付款\", value: \"onetime\" },\n { label: \"分期付款\", value: \"installment\" },\n { label: \"按里程碑付款\", value: \"milestone\" },\n ]}\n />,\n ]}\n />\n )}\n\n <FormInfo\n title=\"其他备注\"\n list={[<TextArea name=\"remark\" label=\"录用备注说明\" block />]}\n />\n\n <SubmitButton type=\"primary\">提交录用信息</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `表单弹窗`,\n description: `展示FormModal的使用,在弹窗中展示表单,适合数据录入、编辑等场景`,\n code: `const {default: FormInfo, useFormModal, fields} = _FormInfo;\nconst {PureGlobal} = global;\nconst {Button, Space} = antd;\nconst {useState} = React;\n\nconst {Input, DatePicker, Select} = fields;\n\nconst EmployeeModal = () => {\n const modal = useFormModal();\n\n const handleAddEmployee = () => {\n const modalApi = modal({\n title: \"新建员工档案\", formProps: {\n onSubmit: (data) => {\n console.log(\"提交数据:\", data);\n modalApi.close();\n },\n }, children: (<FormInfo\n list={[<Input name=\"name\" label=\"员工姓名\" rule=\"REQ\"/>,\n <Input name=\"phone\" label=\"联系电话\" rule=\"REQ PHONE\"/>,\n <DatePicker name=\"joinDate\" label=\"入职日期\" rule=\"REQ\"/>, <Select\n name=\"department\"\n label=\"所属部门\"\n rule=\"REQ\"\n options={[{label: \"技术研发中心\", value: \"tech\"}, {\n label: \"产品管理中心\",\n value: \"product\"\n }, {label: \"市场营销中心\", value: \"marketing\"},]}\n />, <Select\n name=\"position\"\n label=\"职位名称\"\n rule=\"REQ\"\n options={[{label: \"高级工程师\", value: \"senior\"}, {\n label: \"产品经理\",\n value: \"pm\"\n }, {label: \"UI设计师\", value: \"designer\"},]}\n />,]}\n />),\n });\n };\n\n return (<Space>\n <Button type=\"primary\" onClick={handleAddEmployee}>\n 新建员工档案\n </Button>\n <Button onClick={() => modalApi.close()}>关闭</Button>\n </Space>);\n};\n\nconst BaseExample = () => {\n return (<PureGlobal>\n <EmployeeModal/>\n </PureGlobal>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `表单抽屉`,\n description: `展示FormDrawer的使用,在抽屉中展示表单,适合展示更多表单内容的场景`,\n code: `const { default: FormInfo, useFormDrawer, fields } = _FormInfo;\nconst { PureGlobal } = global;\nconst { Button, Space } = antd;\n\nconst { Input, DatePicker, Select, TextArea } = fields;\n\nconst ProjectDrawer = () => {\n const drawer = useFormDrawer();\n\n const handleCreateProject = () => {\n const drawerApi = drawer({\n title: \"发起研发项目\",\n width: 600,\n formProps: {\n onSubmit: (data) => {\n console.log(\"提交数据:\", data);\n drawerApi.close();\n },\n },\n children: (\n <FormInfo\n list={[\n <Input name=\"name\" label=\"项目名称\" rule=\"REQ\" />,\n <TextArea name=\"description\" label=\"项目背景与目标\" block />,\n <DatePicker name=\"startDate\" label=\"计划启动日期\" rule=\"REQ\" />,\n <DatePicker name=\"endDate\" label=\"计划完成日期\" rule=\"REQ\" />,\n <Select\n name=\"projectManager\"\n label=\"项目负责人\"\n rule=\"REQ\"\n options={[\n { label: \"王建国\", value: 1 },\n { label: \"李晓华\", value: 2 },\n { label: \"张思远\", value: 3 },\n ]}\n />,\n <Select\n name=\"projectStatus\"\n label=\"项目阶段\"\n rule=\"REQ\"\n options={[\n { label: \"需求分析\", value: \"requirement\" },\n { label: \"开发实施\", value: \"development\" },\n { label: \"测试验收\", value: \"testing\" },\n { label: \"上线部署\", value: \"deployment\" },\n ]}\n />,\n ]}\n />\n ),\n });\n };\n\n return (\n <Space>\n <Button type=\"primary\" onClick={handleCreateProject}>\n 发起研发项目\n </Button>\n <Button onClick={() => drawerApi.close()}>关闭</Button>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal>\n <ProjectDrawer />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `分步表单弹窗`,\n description: `展示FormStepModal的使用,将表单分为多个步骤,逐步引导用户填写,适合复杂表单场景`,\n code: `const {default: FormInfo, useFormStepModal, fields} = _FormInfo;\nconst {PureGlobal} = global;\nconst {Button, Space, Card, Tag, Divider} = antd;\nconst {useModal} = _Modal;\n\nconst {Input, DatePicker, Select, TextArea, PhoneNumber} = fields;\n\nconst RecruitmentStepModal = () => {\n const modal = useFormStepModal();\n const handleOpenRecruitment = () => {\n const modalApi = modal({\n title: \"人才招聘流程\", items: [{\n title: \"基本信息\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex}) => {\n console.log(\"基本信息提交:\", data);\n console.log(\"步骤缓存:\", stepCacheRef.current);\n }\n }, children: (<FormInfo\n list={[<Input name=\"candidateName\" label=\"候选人姓名\" rule=\"REQ\"/>,\n <PhoneNumber name=\"contactPhone\" label=\"联系电话\" rule=\"REQ\"/>,\n <Input name=\"email\" label=\"电子邮箱\" rule=\"REQ EMAIL\"/>,\n <DatePicker name=\"dateOfBirth\" label=\"出生日期\"/>,]}\n />),\n }, {\n title: \"教育经历\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex}) => {\n console.log(\"教育经历提交:\", data);\n console.log(\"步骤缓存:\", stepCacheRef.current);\n }\n }, children: (<FormInfo\n list={[<Input name=\"university\" label=\"毕业院校\" rule=\"REQ\"/>, <Select\n name=\"educationDegree\"\n label=\"最高学历\"\n rule=\"REQ\"\n options={[{label: \"本科\", value: \"bachelor\"}, {\n label: \"硕士研究生\", value: \"master\"\n }, {label: \"博士研究生\", value: \"doctor\"},]}\n />, <Select\n name=\"major\"\n label=\"专业领域\"\n rule=\"REQ\"\n options={[{label: \"计算机科学与技术\", value: \"cs\"}, {\n label: \"软件工程\", value: \"se\"\n }, {label: \"信息管理与信息系统\", value: \"im\"},]}\n />,]}\n />),\n }, {\n title: \"工作经历\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex, isLastStep}) => {\n console.log(\"工作经历提交:\", data);\n console.log(\"所有步骤缓存数据:\", stepCacheRef.current);\n // 在最后一步合并所有步骤的数据\n const allData = {};\n Object.keys(stepCacheRef.current).forEach(key => {\n Object.assign(allData, stepCacheRef.current[key].data);\n });\n console.log(\"合并后的完整数据:\", allData);\n alert(\"人才信息提交成功!\" + JSON.stringify(allData, null, 2));\n }\n }, children: (<FormInfo\n list={[<Input name=\"lastCompany\" label=\"上家公司名称\"/>, <Select\n name=\"position\"\n label=\"职位级别\"\n options={[{label: \"初级工程师\", value: \"junior\"}, {\n label: \"中级工程师\", value: \"mid\"\n }, {label: \"高级工程师\", value: \"senior\"},]}\n />, <TextArea name=\"workExperience\" label=\"工作经历描述\" block/>,]}\n />),\n },],\n });\n };\n\n return (<Space>\n <Button type=\"primary\" onClick={handleOpenRecruitment}>\n 发起人才招聘\n </Button>\n <Button onClick={() => modalApi.close()}>关闭</Button>\n </Space>);\n};\n\n// 演示 stepCacheRef 的使用\nconst StepCacheExample = () => {\n const modal = useFormStepModal();\n const normalModal = useModal();\n const handleOpen = () => {\n const modalApi = modal({\n title: \"stepCacheRef 演示\", items: [{\n title: \"第一步\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex}) => {\n console.log(\"第一步数据:\", data);\n console.log(\"当前缓存:\", stepCacheRef.current);\n }\n }, children: (<FormInfo\n list={[<Input name=\"field1\" label=\"字段1\" rule=\"REQ\"/>, <Input name=\"field2\" label=\"字段2\"/>,]}\n />),\n }, {\n title: \"第二步\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex}) => {\n console.log(\"第二步数据:\", data);\n console.log(\"当前缓存:\", stepCacheRef.current);\n console.log(\"第一步缓存数据:\", stepCacheRef.current[0]);\n }\n }, children: (<FormInfo\n list={[<Input name=\"field3\" label=\"字段3\" rule=\"REQ\"/>, <Input name=\"field4\" label=\"字段4\"/>,]}\n />),\n }, {\n title: \"第三步\", formProps: {\n onSubmit: (data, {stepCacheRef, currentIndex, isLastStep}) => {\n console.log(\"第三步数据:\", data);\n console.log(\"所有缓存数据:\", stepCacheRef.current);\n\n // 合并所有步骤的数据\n const allData = {};\n Object.keys(stepCacheRef.current).forEach(key => {\n Object.assign(allData, stepCacheRef.current[key].data);\n });\n console.log(\"完整数据:\", allData);\n\n // 显示缓存内容\n const cacheContent = Object.entries(stepCacheRef.current).map(([index, cache]) => ({\n step: index, data: cache.data, output: cache.output\n }));\n\n normalModal({\n children: (<Space direction=\"vertical\" size={16} style={{padding: 24}}>\n <Card title=\"提交成功\" size=\"small\">\n <Space direction=\"vertical\" size={8}>\n {cacheContent.map((item, idx) => (<Card key={idx} size=\"small\" type=\"inner\"\n title={\\`步骤 \\${parseInt(item.step) + 1}\\`}>\n <Space direction=\"vertical\" size={4}>\n {Object.entries(item.data).map(([key, value]) => (\n <Tag key={key}>{key}: {String(value)}</Tag>))}\n </Space>\n </Card>))}\n </Space>\n </Card>\n <Button onClick={() => modalApi.close()}>关闭</Button>\n </Space>), footerButtons: []\n });\n }\n }, children: (<FormInfo\n list={[<Input name=\"field5\" label=\"字段5\" rule=\"REQ\"/>, <Input name=\"field6\" label=\"字段6\"/>,]}\n />),\n },],\n });\n };\n\n return (<Button onClick={handleOpen}>stepCacheRef 演示</Button>);\n};\n\nconst BaseExample = () => {\n return (<PureGlobal>\n <Space direction=\"vertical\">\n <RecruitmentStepModal/>\n <Divider/>\n <Space>\n <StepCacheExample/>\n </Space>\n </Space>\n </PureGlobal>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `useFormContext`,\n description: `展示如何使用useFormContext Hook访问表单API,实现查看值、设置值、校验、重置等操作`,\n code: `const { default: FormInfo, Form, useFormContext, fields } = _FormInfo;\nconst { Space, Card, Button, Tag, Divider } = antd;\nconst { useState } = React;\n\nconst { Input, DatePicker, Select } = fields;\n\nconst FormActions = () => {\n const { openApi, formData } = useFormContext();\n const [showData, setShowData] = useState(false);\n\n return (\n <Space direction=\"vertical\" size={16} style={{ width: \"100%\" }}>\n <Space wrap>\n <Button\n type=\"primary\"\n onClick={() => {\n openApi.setFields(\n [\n { name: \"employeeName\", value: \"王建国\" },\n { name: \"workEmail\", value: \"wangjianguo@company.com\" },\n { name: \"department\", value: \"tech\" },\n ],\n { runValidate: false }\n );\n }}\n >\n 填充员工信息\n </Button>\n <Button\n onClick={() => {\n setShowData(!showData);\n }}\n >\n {showData ? \"隐藏数据\" : \"查看数据\"}\n </Button>\n <Button\n onClick={() => {\n openApi.validateAll();\n }}\n >\n 校验表单\n </Button>\n <Button onClick={openApi.reset}>重置表单</Button>\n </Space>\n\n {showData && (\n <Card title=\"当前表单数据\" size=\"small\">\n <Space direction=\"vertical\" size={8}>\n {Object.entries(formData).map(([key, value]) => (\n <Tag key={key} color=\"blue\">\n <strong>{key}</strong>:{\" \"}\n {typeof value === \"object\" && value !== null\n ? JSON.stringify(value)\n : String(value)}\n </Tag>\n ))}\n </Space>\n </Card>\n )}\n <Divider />\n </Space>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Form\n onSubmit={(data) => {\n console.log(\"提交数据:\", data);\n alert(\"员工信息保存成功!\");\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"员工基本信息\"\n list={[\n <Input name=\"employeeName\" label=\"员工姓名\" rule=\"REQ\" />,\n <Input name=\"workEmail\" label=\"工作邮箱\" rule=\"REQ EMAIL\" />,\n <DatePicker name=\"onboardingDate\" label=\"入职日期\" />,\n <Select\n name=\"department\"\n label=\"所属部门\"\n options={[\n { label: \"技术研发中心\", value: \"tech\" },\n { label: \"产品管理中心\", value: \"product\" },\n { label: \"市场营销中心\", value: \"marketing\" },\n ]}\n />,\n ]}\n />\n\n <FormActions />\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `FormApiButton`,\n description: `展示FormApiButton的使用,通过按钮访问表单API,实现各种表单操作`,\n code: `const { default: FormInfo, Form, FormApiButton, fields } = _FormInfo;\nconst { Space, Flex } = antd;\n\nconst { Input, DatePicker, Select } = fields;\n\nconst BaseExample = () => {\n return (\n <Form\n onSubmit={(data) => {\n console.log(\"提交数据:\", data);\n alert(\"员工信息保存成功!\");\n }}\n >\n <Space direction=\"vertical\" size={16} style={{ width: \"100%\" }}>\n <FormInfo\n title=\"员工基本信息\"\n list={[\n <Input name=\"employeeName\" label=\"员工姓名\" rule=\"REQ\" />,\n <Input name=\"workEmail\" label=\"工作邮箱\" rule=\"REQ EMAIL\" />,\n <DatePicker name=\"onboardingDate\" label=\"入职日期\" />,\n <Select\n name=\"department\"\n label=\"所属部门\"\n options={[\n { label: \"技术研发中心\", value: \"tech\" },\n { label: \"产品管理中心\", value: \"product\" },\n { label: \"市场营销中心\", value: \"marketing\" },\n ]}\n />,\n ]}\n />\n\n <FormInfo\n list={[\n <Flex gap={8} wrap>\n <FormApiButton\n type=\"default\"\n onClick={({ openApi, formData }) => {\n alert(\"当前表单数据:\" + JSON.stringify(formData, null, 2));\n }}\n >\n 查看表单数据\n </FormApiButton>\n <FormApiButton\n type=\"default\"\n onClick={({ openApi }) => {\n openApi.setFields(\n [\n { name: \"employeeName\", value: \"王建国\" },\n { name: \"workEmail\", value: \"wangjianguo@company.com\" },\n { name: \"department\", value: \"tech\" },\n ],\n { runValidate: false }\n );\n }}\n >\n 填充员工信息\n </FormApiButton>\n <FormApiButton\n type=\"default\"\n onClick={({ openApi }) => {\n openApi.validateAll();\n }}\n >\n 校验表单\n </FormApiButton>\n <FormApiButton\n type=\"default\"\n danger\n onClick={({ openApi }) => {\n openApi.reset();\n }}\n >\n 重置表单\n </FormApiButton>\n <FormApiButton\n type=\"primary\"\n htmlType=\"submit\"\n onClick={({ openApi }) => {\n openApi.submit();\n }}\n >\n 保存员工信息\n </FormApiButton>\n </Flex>,\n ]}\n />\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `自定义校验规则`,\n description: `展示如何定义自定义校验规则,包括同步校验、异步校验和字段间联动校验`,\n code: `const { default: FormInfo, Form, SubmitButton, ErrorTip, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { Space, Alert } = antd;\n\nconst { Input, Password, Select } = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n return (\n <Form\n rules={{\n // 自定义规则:密码强度校验\n PASSWORD_STRENGTH: (value) => {\n const hasLetter = /[a-zA-Z]/.test(value);\n const hasNumber = /[0-9]/.test(value);\n const hasSpecial = /[!@#\\$%^&*]/.test(value);\n if (!hasLetter || !hasNumber || !hasSpecial) {\n return {\n result: false,\n errMsg: \"密码必须包含字母、数字和特殊字符\",\n };\n }\n return { result: true, errMsg: \"\" };\n },\n // 自定义规则:异步校验用户名\n USERNAME_EXISTS: (value) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n const exists = [\"wangming\", \"lihua\", \"zhangwei\"].includes(value);\n resolve({\n result: !exists,\n errMsg: exists ? \"该用户名已被占用\" : \"\",\n });\n }, 800);\n });\n },\n }}\n onSubmit={(data) => {\n modal({\n title: \"管理员账号创建成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <Alert\n message=\"自定义校验规则说明\"\n description=\"PASSWORD_STRENGTH-密码强度校验(必须包含字母、数字和特殊字符)| USERNAME_EXISTS-异步校验用户名是否已存在\"\n type=\"info\"\n />\n\n <FormInfo\n title=\"管理员账号配置\"\n list={[\n <ErrorTip name=\"username\">\n <Input\n name=\"username\"\n label=\"管理员用户名\"\n rule=\"REQ LEN-4-16 USERNAME_EXISTS\"\n tips=\"4-16位,wangming、lihua、zhangwei已被占用\"\n />\n </ErrorTip>,\n <Password\n name=\"password\"\n label=\"设置密码\"\n rule=\"REQ LEN-8-20 PASSWORD_STRENGTH\"\n tips=\"至少8位,包含字母、数字和特殊字符\"\n />,\n <Password\n name=\"confirmPassword\"\n label=\"确认密码\"\n rule=\"REQ\"\n tips=\"请再次输入密码\"\n />,\n <Select\n name=\"adminRole\"\n label=\"管理权限级别\"\n rule=\"REQ\"\n options={[\n { label: \"系统管理员\", value: \"superadmin\" },\n { label: \"部门管理员\", value: \"department\" },\n { label: \"内容管理员\", value: \"content\" },\n ]}\n />,\n ]}\n />\n\n <SubmitButton type=\"primary\">创建管理员账号</SubmitButton>\n </Space>\n </Form>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n}]\n},{\n title: `地址选择`,\n description: `展示AddressSelect地址选择组件,支持省市区三级联动选择`,\n code: `const { AddressSelect: _AddressSelect, AddressInput: _AddressInput } =\n _FormInfo;\nconst { PureGlobal } = global;\nconst { Space, Button } = antd;\nconst { default: Content } = _Content;\nconst { range, uniqueId } = lodash;\n\nconst AddressSelect = _AddressSelect.Field;\nconst AddressEnum = _AddressSelect.AddressEnum;\nconst AddressInput = _AddressInput.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"业务区域多选\",\n content: (\n <AddressSelect\n maxLength={3}\n defaultValue={[\"110\"]}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"业务区域单选\",\n content: (\n <AddressSelect\n single\n defaultValue={\"110\"}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"modal业务区域多选\",\n content: (\n <AddressSelect\n maxLength={3}\n isPopup={false}\n defaultValue={[\"110\"]}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"modal业务区域单选\",\n content: (\n <AddressSelect\n isPopup={false}\n single\n defaultValue={\"110\"}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"valueType为all\",\n content: (\n <AddressSelect\n valueType=\"all\"\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"地址显示\",\n content: <AddressEnum name=\"270070\" />,\n },\n {\n label: \"显示父级\",\n content: <AddressEnum name=\"270070\" displayParent />,\n },\n {\n label: \"详细地址输入\",\n content: (\n <AddressInput\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n ]}\n />\n );\n};\n\nrender(\n <div className=\"input\">\n <BaseExample />\n </div>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_45\n}]\n},{\n title: `级联选择`,\n description: `展示级联选择组件,支持多级联动选择`,\n code: `const { Cascader: _Cascader } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst { range, get } = lodash;\n\nconst Cascader = _Cascader.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"一次性获取数据\",\n content: (\n <Cascader\n onlyAllowLastLevel\n single\n api={{\n loader: async () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n id: \"client\",\n value: \"client\",\n type: \"module\",\n name: \"客户管理\",\n label: \"客户管理\",\n children: [\n {\n id: \"client-list\",\n value: \"client-list\",\n type: \"feature\",\n name: \"客户列表\",\n label: \"客户列表\",\n },\n {\n id: \"client-detail\",\n value: \"client-detail\",\n type: \"module\",\n name: \"客户详情\",\n label: \"客户详情\",\n children: [\n {\n id: \"contract\",\n value: \"contract\",\n type: \"module\",\n name: \"合同管理\",\n label: \"合同管理\",\n },\n ],\n },\n {\n id: \"client-form\",\n value: \"client-form\",\n type: \"feature\",\n name: \"客户表单\",\n label: \"客户表单\",\n children: [\n {\n id: \"taxpayerIdNumber\",\n value: \"taxpayerIdNumber\",\n type: \"feature\",\n name: \"税号\",\n label: \"税号\",\n },\n ],\n },\n ],\n },\n {\n id: \"position\",\n value: \"position\",\n type: \"module\",\n name: \"招聘管理\",\n label: \"招聘管理\",\n children: [\n {\n id: \"position-list\",\n value: \"position-list\",\n type: \"feature\",\n name: \"职位列表\",\n label: \"职位列表\",\n },\n {\n id: \"position-detail\",\n value: \"position-detail\",\n type: \"module\",\n name: \"职位详情\",\n label: \"职位详情\",\n },\n {\n id: \"position-form\",\n value: \"position-form\",\n type: \"feature\",\n name: \"职位表单\",\n label: \"职位表单\",\n children: [\n {\n id: \"industry\",\n value: \"industry\",\n type: \"feature\",\n name: \"行业选择\",\n label: \"行业选择\",\n },\n ],\n },\n ],\n },\n ]);\n }, 1000);\n });\n },\n }}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"分层加载数据\",\n content: (\n <Cascader\n openLoadData\n onSearch={async (searchText) => {\n return range(0, 20).map((key) => {\n const parentId = \"2\";\n return {\n id: \\`\\${parentId ? \\`\\${parentId}-\\` : \"\"}\\${key + 1}\\`,\n label: \\`部门-\\${searchText}-\\${\n parentId ? \\`\\${parentId}-\\` : \"\"\n }\\${key + 1}\\`,\n parentId,\n };\n });\n }}\n api={{\n loader: async ({ data }) => {\n const parentId = get(data, \"id\", \"\");\n const level = parentId.split(\"-\").length;\n console.log(\"loadData\", parentId, level);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(\n range(0, 20).map((key) => {\n return Object.assign(\n {\n id: \\`\\${parentId ? \\`\\${parentId}-\\` : \"\"}\\${key + 1}\\`,\n label: \\`部门-\\${parentId ? \\`\\${parentId}-\\` : \"\"}\\${\n key + 1\n }\\`,\n parentId,\n },\n level >= 3 ? { children: null } : {}\n );\n })\n );\n }, 1000);\n });\n },\n }}\n />\n ),\n },\n {\n label: \"modal分层加载数据\",\n content: (\n <Cascader\n openLoadData\n isPopup={false}\n api={{\n loader: async ({ data }) => {\n const parentId = get(data, \"id\", \"\");\n const level = parentId.split(\"-\").length;\n console.log(\"loadData\", parentId, level);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(\n range(0, 20).map((key) => {\n return Object.assign(\n {\n id: \\`\\${parentId ? \\`\\${parentId}-\\` : \"\"}\\${key + 1}\\`,\n label: \\`部门-\\${parentId ? \\`\\${parentId}-\\` : \"\"}\\${\n key + 1\n }\\`,\n parentId,\n },\n level >= 3 ? { children: null } : {}\n );\n })\n );\n }, 1000);\n });\n },\n }}\n />\n ),\n },\n ]}\n />\n );\n};\n\nrender(\n <PureGlobal>\n <div className=\"input\">\n <BaseExample />\n </div>\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_45\n}]\n},{\n title: `职能选择`,\n description: `展示FunctionSelect职能选择组件,支持多级职能树选择`,\n code: `const { FunctionSelect: _FunctionSelect } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst { range, get } = lodash;\n\nconst FunctionSelect = _FunctionSelect.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"职能选择\",\n content: (\n <FunctionSelect\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"modal职能选择\",\n content: (\n <FunctionSelect\n isPopup={false}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"职能选择无搜索\",\n content: (\n <FunctionSelect\n search={null}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"职能枚举显示\",\n content: <FunctionSelect.Enum name=\"001\" />,\n },\n ]}\n />\n );\n};\n\nrender(\n <div className=\"input\">\n <BaseExample />\n </div>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_45\n}]\n},{\n title: `行业选择`,\n description: `展示IndustrySelect行业选择组件,支持多级行业树选择`,\n code: `const { IndustrySelect: _IndustrySelect } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst { range, get } = lodash;\n\nconst IndustrySelect = _IndustrySelect.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"所属行业\",\n content: (\n <IndustrySelect\n defaultValue={[\"001\"]}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"modal所属行业\",\n content: (\n <IndustrySelect\n isPopup={false}\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n {\n label: \"行业枚举显示\",\n content: <IndustrySelect.Enum name=\"004\" />,\n },\n ]}\n />\n );\n};\n\nrender(\n <div className=\"input\">\n <BaseExample />\n </div>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_45\n}]\n},{\n title: `金额输入`,\n description: `展示MoneyInput金额输入组件,支持金额格式化和单位选择`,\n code: `const { MoneyInput: _MoneyInput } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst MoneyInput = _MoneyInput.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"合同金额输入\",\n content: <MoneyInput />,\n },\n ]}\n />\n );\n};\n\nrender(\n <PureGlobal>\n <div className=\"input\">\n <BaseExample />\n </div>\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n}]\n},{\n title: `电话号码`,\n description: `展示PhoneNumber手机号输入组件,支持手机号格式化和校验`,\n code: `const { PhoneNumber: _PhoneNumber } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst PhoneNumber = _PhoneNumber.Field;\n\nconst BaseExample = () => {\n return (\n <Content\n col={2}\n list={[\n {\n label: \"联系电话\",\n content: (\n <PhoneNumber\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n ]}\n />\n );\n};\n\nrender(\n <PureGlobal>\n <div className=\"input\">\n <BaseExample />\n </div>\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n}]\n},{\n title: `薪资范围`,\n description: `展示SalaryInput薪资范围输入组件,支持薪资类型、月薪/年薪选择和范围校验`,\n code: `const { SalaryInput, Form } = _FormInfo;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst SalaryInputField = SalaryInput.Field;\n\nconst BaseExample = () => {\n return (\n <div>\n <Content\n col={1}\n list={[\n {\n label: \"薪资范围\",\n content: (\n <SalaryInputField\n onChange={(value) => {\n console.log(value);\n }}\n />\n ),\n },\n ]}\n />\n <Form\n rules={{\n SALARYRANGE: ({ min, max, type }) => {\n if (type !== 1) {\n if (!min || !max) {\n return {\n result: false,\n errMsg: \\`\\${!min ? \"最低薪资\" : \"最高薪资\"}不能为空\\`,\n };\n }\n if (min > max) {\n return {\n result: false,\n errMsg: \"最高薪资应大于最低薪资\",\n };\n }\n }\n return {\n result: true,\n errMsg: \"\",\n };\n },\n }}\n data={{ salaryRange: { type: 5, month: 12 } }}\n >\n <SalaryInput\n name=\"salaryRange\"\n label=\"薪资范围\"\n rule=\"REQ SALARYRANGE\"\n showMonth\n remindUnit\n />\n </Form>\n </div>\n );\n};\n\nrender(\n <PureGlobal>\n <div className=\"input\">\n <BaseExample />\n </div>\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_44\n}]\n},{\n title: `helperGuideName 和 lang`,\n description: `展示 helperGuideName 为字段添加帮助指引功能,以及 lang 配置实现多语言支持`,\n code: `const {default: FormInfo, Form, SubmitButton, fields, List} = _FormInfo;\nconst {useModal} = _Modal;\nconst {PureGlobal} = global;\nconst {Space, Alert, Radio} = antd;\nconst {useState} = React;\n\nconst {Input, TextArea, Select} = fields;\n\nconst BaseExample = () => {\n const modal = useModal();\n const [helperGuideName, setHelperGuideName] = useState(\"employee-form\");\n const [langOpen, setLangOpen] = useState(true);\n\n return (<Space direction=\"vertical\" size={24} style={{width: \"100%\"}}>\n <Alert\n message=\"helperGuideName 和 lang 使用说明\"\n description=\"helperGuideName-为字段添加帮助指引功能 | lang-启用多语言支持,为每个字段生成多语言版本\"\n type=\"info\"\n />\n\n <Space direction=\"vertical\" size={16} style={{width: \"100%\"}}>\n <div>\n <span style={{marginRight: 12, fontWeight: 500}}>帮助指引名称:</span>\n <Radio.Group\n value={helperGuideName}\n onChange={(e) => setHelperGuideName(e.target.value)}\n >\n <Radio.Button value=\"employee-form\">启用 (employee-form)</Radio.Button>\n <Radio.Button value=\"\">禁用</Radio.Button>\n </Radio.Group>\n </div>\n\n <div>\n <span style={{marginRight: 12, fontWeight: 500}}>多语言配置:</span>\n <Radio.Group\n value={langOpen}\n onChange={(e) => setLangOpen(e.target.value)}\n >\n <Radio.Button value={true}>中文+英文</Radio.Button>\n <Radio.Button value={false}>仅中文</Radio.Button>\n </Radio.Group>\n </div>\n </Space>\n\n <Form\n helperGuideName={helperGuideName}\n lang={langOpen ? [\"cn\", {\n name: \"EnUS\", label: \"英文\", options: {\n labelTransform: (label) => label + \"(en)\",\n ignore: [{name: \"avatar\"}, {name: \"photo\"}],\n disabled: [{name: \"file\"}], //fields:[{name:'name'}]\n },\n },] : undefined}\n onSubmit={(data) => {\n modal({\n title: \"员工档案提交成功\", children: <pre>{JSON.stringify(data, null, 2)}</pre>,\n });\n }}\n >\n <Space direction=\"vertical\" size={16}>\n <FormInfo\n title=\"基本信息\"\n list={[<Input name=\"name\" label=\"员工姓名\" rule=\"REQ\"/>,\n <Input name=\"email\" label=\"工作邮箱\" rule=\"REQ EMAIL\"/>,\n <TextArea name=\"description\" label=\"个人简介\" block/>,]}\n />\n\n <FormInfo\n title=\"工作信息\"\n list={[<Select\n name=\"department\"\n label=\"所属部门\"\n rule=\"REQ\"\n options={[{label: \"技术研发中心\", value: \"tech\"}, {\n label: \"产品管理中心\", value: \"product\"\n }, {label: \"市场营销中心\", value: \"marketing\"},]}\n />, <Select\n name=\"position\"\n label=\"职位名称\"\n rule=\"REQ\"\n options={[{label: \"高级工程师\", value: \"senior\"}, {\n label: \"产品经理\", value: \"pm\"\n }, {label: \"UI设计师\", value: \"designer\"},]}\n />,]}\n />\n\n <List\n name=\"skills\"\n title=\"专业技能列表\"\n itemTitle={({index}) => \\`技能 \\${index + 1}\\`}\n list={[<Input name=\"name\" label=\"技能名称\" rule=\"REQ\"/>, <Select\n name=\"level\"\n label=\"熟练程度\"\n rule=\"REQ\"\n options={[{label: \"初级\", value: \"beginner\"}, {\n label: \"中级\", value: \"intermediate\"\n }, {label: \"高级\", value: \"advanced\"},]}\n />,]}\n />\n\n <SubmitButton type=\"primary\">提交员工档案</SubmitButton>\n </Space>\n </Form>\n </Space>);\n};\n\nrender(<PureGlobal\n preset={{\n enums: {\n helperGuide: () => [{\n value: \"employee-form-name\", content: \"请输入员工的真实姓名,用于身份识别和档案管理\", url: \"#\",\n }, {\n value: \"employee-form-email\", content: \"请输入有效的电子邮箱地址,用于接收工作通知和系统消息\", url: \"#\",\n }, {\n value: \"employee-form-department\",\n content: \"请选择员工所属的部门,部门决定了员工的汇报关系和权限范围\",\n url: \"#\",\n }, {\n value: \"employee-form-position\", content: \"请选择员工的职位,职位决定了员工的级别和职责范围\", url: \"#\",\n }, {\n value: \"employee-form-skills-name\", content: \"请填写员工掌握的技能名称,如编程语言、专业技能等\", url: \"#\",\n }, {\n value: \"employee-form-skills-level\",\n content: \"请选择员工对该技能的熟练程度,便于合理分配工作任务\",\n url: \"#\",\n },],\n },\n }}\n>\n <BaseExample/>\n</PureGlobal>);\n\n`,\n scope: [{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_40\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_41\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_42\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_43\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_52 from '@components/Global';\nimport * as component_53 from 'antd';\nimport * as component_54 from '@components/Icon';\nconst readmeConfig = {\n name: `Global`,\n summary: `<p>Global 是 components-core 组件库的全局配置组件,负责为整个应用提供统一的上下文环境、样式主题和全局配置。它集成了 Antd ConfigProvider、国际化支持、字体加载、主题定制等功能,是使用 components-core 组件库时必须包含的最外层组件。</p>\n<p><strong>核心特性</strong></p>\n<ul>\n<li><strong>统一的主题管理</strong>:支持自定义主题色,自动生成主题色透明度渐变,提供丰富的 CSS 变量用于全局样式控制</li>\n<li><strong>国际化支持</strong>:内置中文和英文两种语言,支持 Antd 组件库的国际化以及第三方组件的本地化</li>\n<li><strong>全局上下文管理</strong>:通过 preset 参数统一配置权限、API、枚举等全局资源,所有子组件都可以通过 usePreset Hook 访问</li>\n<li><strong>错误边界处理</strong>:自动捕获页面错误并展示友好的错误提示,提升用户体验</li>\n<li><strong>字体资源管理</strong>:自动加载图标字体,支持自定义字体配置</li>\n<li><strong>响应式设计</strong>:提供多种尺寸的文字、颜色和行高变量,适配不同场景</li>\n</ul>\n<p><strong>适用场景</strong></p>\n<p>在使用 components-core 组件库的任何业务系统中,都需要将 Global 组件放置在应用根位置,并按照要求配置 preset 参数。这样所有 components-core 的组件才能正确获取全局配置并正常工作。</p>\n<p><strong>Preset 配置说明</strong></p>\n<p>preset 是一个对象,包含 components-core 组件系统所需的全局配置,以下是常用的配置项:</p>\n<table>\n<thead>\n<tr>\n<th>名称</th>\n<th>说明</th>\n<th>类型</th>\n<th>使用组件</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>permissions</td>\n<td>配置功能权限列表,Permissions根据该列表里面是否存在某权限名称判断用户是否具有该功能权限,来控制对应操作行为</td>\n<td>array</td>\n<td>Permissions</td>\n</tr>\n<tr>\n<td>ajax</td>\n<td>用于发送ajax请求的方法,一般情况下其应该是一个axios对象</td>\n<td>object</td>\n<td>Image</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>用于和后端进行一些交互行为的接口集合</td>\n<td>object</td>\n<td>Image</td>\n</tr>\n<tr>\n<td>apis.oss</td>\n<td>用于通过一个ossId向后端oss服务获取一个可以访问到指定文件的url</td>\n<td>object</td>\n<td>Image</td>\n</tr>\n<tr>\n<td>apis.ossUpload</td>\n<td>用于向oss服务上传一个文件</td>\n<td>object</td>\n<td>FormInfo.Upload,FormInfo.Avatar</td>\n</tr>\n<tr>\n<td>features</td>\n<td>用于配置系统的特性参数</td>\n<td>object</td>\n<td>Features</td>\n</tr>\n<tr>\n<td>features.profile</td>\n<td>系统的特性列表参考组件Features</td>\n<td>object</td>\n<td>Features</td>\n</tr>\n<tr>\n<td>features.debug</td>\n<td>特性的调试模式,可以在控制台打印Features的id和状态</td>\n<td>boolean</td>\n<td>Features</td>\n</tr>\n<tr>\n<td>enums</td>\n<td>公共枚举值,详情参看Enum组件</td>\n<td>object</td>\n<td>Enum</td>\n</tr>\n<tr>\n<td>enums.helperGuide</td>\n<td>帮助文档枚举配置</td>\n<td>function</td>\n<td>HelperGuide</td>\n</tr>\n<tr>\n<td>formInfo</td>\n<td>表单配置</td>\n<td>object</td>\n<td>FormInfo.formModule</td>\n</tr>\n<tr>\n<td>formInfo.rules</td>\n<td>表单规则配置</td>\n<td>object</td>\n<td>FormInfo.formModule</td>\n</tr>\n</tbody>\n</table>\n<p><strong>样式管理</strong></p>\n<p>Global 组件提供了全局样式管理功能,所有全局覆盖性的样式、Antd 的样式覆盖都应放置在此组件中。组件内置了丰富的 CSS 变量,包括字体大小、颜色、行高、圆角、背景色等,开发者可以通过这些变量快速定制应用风格。</p>\n<p><strong>字体配置</strong></p>\n<p>如需自定义图标字体,请按照以下步骤操作:</p>\n<ol>\n<li>将 iconfont 上下载的字体包解压后放在 public 文件夹下</li>\n<li>更新 src/common/params.js 中的变量 iconfontBase</li>\n<li>修改后构建项目并发布到对应环境</li>\n</ol>\n<p><strong>组件位置</strong></p>\n<p>Global 组件必须放置在应用的最外层,包裹所有其他组件,确保全局配置能够正确传递到所有子组件。</p>`,\n \n \n api: `<h3>Global</h3>\n<p>Global 组件是 components-core 的全局配置组件,必须放置在应用最外层。它提供了全局上下文、主题配置、国际化支持、错误边界等功能。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>preset</td>\n<td>object</td>\n<td>否</td>\n<td>{}</td>\n<td>全局预设参数,可通过 usePreset 获取,由业务系统设置</td>\n</tr>\n<tr>\n<td>themeToken</td>\n<td>object</td>\n<td>否</td>\n<td>{}</td>\n<td>主题配置,参考 Antd 的 themeToken,一般只需设置 {colorPrimary}</td>\n</tr>\n<tr>\n<td>init</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>初始化方法,在系统首次加载时执行,可返回 Promise,用于放置系统显示前的异步操作</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n<td>子组件</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义类名</td>\n</tr>\n</tbody>\n</table>\n<h3>PureGlobal</h3>\n<p>纯全局组件,API 与 Global 相同。去除了页面错误捕获和 container-body 类名带来的默认最小宽度等样式设置,主要用于组件库的演示环境和弹窗中。</p>\n<h3>GlobalProvider</h3>\n<p>全局上下文提供者组件,是 Global 和 PureGlobal 的底层实现,一般不直接使用。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>preset</td>\n<td>object</td>\n<td>否</td>\n<td>{locale: \"zh-CN\", apis: {}}</td>\n<td>全局预设参数</td>\n</tr>\n<tr>\n<td>themeToken</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>主题配置</td>\n</tr>\n<tr>\n<td>init</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>初始化方法</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n<td>子组件</td>\n</tr>\n</tbody>\n</table>\n<h3>usePreset</h3>\n<p>获取预设的 preset 参数 Hook。已确定的系统需要使用的 key 值包括:permissions、apis、formOptions、modalOptions。</p>\n<h4>返回值</h4>\n<p>返回 preset 对象,包含所有通过 Global 组件传入的全局配置。</p>\n<h3>useGlobalContext</h3>\n<p>获取和设置全局状态的 Hook。该状态保存在 Global 组件一级,不会随着内部组件的销毁而销毁。主要用于组件内部,业务应避免使用该 API 设置新的 global 变量。业务如有需要应自行在顶级组件中设置 context。</p>\n<h4>参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>globalKey</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>全局参数的 key。当存在 globalKey 时,获取和设置的是 global[key],否则获取和设置的是整个 global 对象。除非存在多个 key-value,否则不推荐直接使用不存在 globalKey 的情况</td>\n</tr>\n</tbody>\n</table>\n<h4>返回值</h4>\n<p>返回包含 global 和 setGlobal 的对象:</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>global</td>\n<td>any</td>\n<td>当前的 global 值</td>\n</tr>\n<tr>\n<td>setGlobal</td>\n<td>function</td>\n<td>设置当前的 global 值</td>\n</tr>\n</tbody>\n</table>\n<h3>useGlobalValue</h3>\n<p>获取指定 key 的全局值的 Hook,类似 useGlobalContext 的简化版本。</p>\n<h4>参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>globalKey</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>要获取的全局参数的 key</td>\n</tr>\n</tbody>\n</table>\n<h4>返回值</h4>\n<p>返回指定 key 对应的 global 值。</p>\n<h3>GlobalValue</h3>\n<p>通过 render props 模式获取指定 global 值的组件。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>globalKey</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>要获取的全局参数的 key</td>\n</tr>\n<tr>\n<td>children</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n<td>渲染函数,接收 {value} 参数</td>\n</tr>\n</tbody>\n</table>\n<h3>containerClassName</h3>\n<p>Global 组件容器的 CSS 类名常量。当需要使用 CSS 选择器选中 Global 组件容器时,可以使用该常量确保选择器的准确性。</p>\n<p>该值是 Global 组件内部使用的 CSS 类名的转义版本,用于处理类名中的特殊字符(如 + 和 /),确保在 CSS 选择器中能够正确匹配。</p>\n<h3>GlobalSetting</h3>\n<p>设置全局值的组件(文档中未详细说明具体用法)。</p>\n<h3>SetGlobal</h3>\n<p>设置全局值的组件,支持条件渲染和函数作为 children。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>globalKey</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>要设置的全局参数的 key</td>\n</tr>\n<tr>\n<td>value</td>\n<td>any</td>\n<td>是</td>\n<td>-</td>\n<td>要设置的值</td>\n</tr>\n<tr>\n<td>needReady</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否需要等待 global 有值后再渲染 children</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode | function</td>\n<td>是</td>\n<td>-</td>\n<td>子组件,当为函数时会接收 {global, setGlobal} 参数</td>\n</tr>\n</tbody>\n</table>\n<h3>GetGlobal</h3>\n<p>获取全局值的组件,通过 render props 模式访问。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>globalKey</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>要获取的全局参数的 key</td>\n</tr>\n<tr>\n<td>children</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n<td>渲染函数,接收 {value} 参数</td>\n</tr>\n</tbody>\n</table>\n<h3>containerClassName</h3>\n<p>Global 组件容器的 CSS 类名常量。当需要使用 CSS 选择器选中 Global 组件容器时,可以使用该常量确保选择器的准确性。</p>\n<p>该值是 Global 组件内部使用的 CSS 类名的转义版本,用于处理类名中的特殊字符(如 + 和 /),确保在 CSS 选择器中能够正确匹配。</p>`,\n example: {\n isFull: false,\n className: `Global_4cc66`,\n style: `.Global_4cc66 .label {\n font-weight: bold;\n}`,\n list: [{\n title: `基本示例`,\n description: `展示了文字大小颜色行高的设置`,\n code: `const { PureGlobal } = _Global;\nconst { Space, Divider } = antd;\nconst BaseExample = () => {\n return (\n <PureGlobal>\n <Space direction=\"vertical\">\n <div className=\"label\">文字大小:</div>\n <div style={{ fontSize: 'var(--font-size-large)' }}>大号文字</div>\n <div>默认大小文字</div>\n <div style={{ fontSize: 'var(--font-size-small)' }}>小号文字</div>\n <Divider />\n <div className=\"label\">文字颜色:</div>\n <div style={{ color: 'var(--font-color)' }}>默认颜色</div>\n <div style={{ color: 'var(--font-color-grey)' }}>灰色</div>\n <div style={{ color: 'var(--font-color-grey-1)' }}>灰色1</div>\n <div style={{ color: 'var(--font-color-grey-2)' }}>灰色2</div>\n <Divider />\n <div className=\"label\">行高:</div>\n <div style={{ lineHeight: 'var(--line-height-large)' }}>\n 宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高宽松行高\n </div>\n <div>\n 默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高默认行高\n </div>\n <div style={{ lineHeight: 'var(--line-height-small)' }}>\n 紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高紧凑行高\n </div>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n},{\n title: `Preset 配置`,\n description: `展示了 preset 全局配置的使用方法`,\n code: `const { PureGlobal, usePreset } = _Global;\nconst { Button, Space, Typography, Card } = antd;\n\nconst { Text } = Typography;\n\n// 模拟的 preset 配置\nconst mockPreset = {\n locale: 'zh-CN',\n permissions: ['user:view', 'user:edit', 'user:delete'],\n apis: {\n getUserList: '/api/users',\n updateUser: '/api/user/update'\n },\n enums: {\n status: {\n active: '启用',\n inactive: '停用'\n }\n },\n features: {\n debug: true,\n profile: 'production'\n }\n};\n\nconst PresetExample = () => {\n const preset = usePreset();\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"Preset 配置信息\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>语言设置:</Text>\n <Text>{preset.locale || '未设置'}</Text>\n </div>\n <div>\n <Text strong>权限列表:</Text>\n <Text>{preset.permissions?.join(', ') || '未设置'}</Text>\n </div>\n <div>\n <Text strong>API 接口:</Text>\n <Text code>{preset.apis?.getUserList || '未设置'}</Text>\n </div>\n <div>\n <Text strong>状态枚举:</Text>\n <Text>{JSON.stringify(preset.enums?.status) || '未设置'}</Text>\n </div>\n <div>\n <Text strong>特性配置:</Text>\n <Text>debug: {preset.features?.debug?.toString() || '未设置'}, profile: {preset.features?.profile || '未设置'}</Text>\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n preset 是通过 Global 组件传入的全局配置,所有子组件都可以通过 usePreset Hook 访问。\n 在实际业务中,preset 通常包含权限列表、API 接口、枚举值等全局配置信息。\n </Text>\n </Card>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal preset={mockPreset}>\n <PresetExample />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n},{\n title: `主题配置`,\n description: `展示了主题色的自定义和预览效果`,\n code: `const { PureGlobal } = _Global;\nconst { Space, Button, Card, ColorPicker, Typography, Divider } = antd;\n\nconst { Text, Title } = Typography;\n\nconst ThemeExample = ({ themeToken }) => {\n const primaryColor = themeToken?.colorPrimary || '#4096ff';\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"主题色演示\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>当前主题色:</Text>\n <span style={{\n display: 'inline-block',\n width: '24px',\n height: '24px',\n backgroundColor: primaryColor,\n marginLeft: '8px',\n borderRadius: '4px',\n border: '1px solid #d9d9d9'\n }} />\n <Text code style={{ marginLeft: '8px' }}>{primaryColor}</Text>\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <div>\n <Text strong>主色按钮:</Text>\n <Button type=\"primary\" style={{ marginLeft: '8px' }}>\n 主色按钮\n </Button>\n </div>\n <div>\n <Text strong>链接文字:</Text>\n <Typography.Link style={{ marginLeft: '8px' }}>\n 链接文字\n </Typography.Link>\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <div>\n <Text strong>Alert 组件(使用主题色):</Text>\n <Space direction=\"vertical\" style={{ width: '100%', marginTop: '8px' }}>\n <Button type=\"primary\">Primary 按钮</Button>\n <Button danger>Danger 按钮</Button>\n </Space>\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 通过 themeToken 属性可以自定义主题色。Global 组件会自动根据主题色生成透明度渐变,\n 并应用到所有使用主题色的组件上,包括按钮、链接、输入框等。\n </Text>\n </Card>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n const [color, setColor] = React.useState('#4096ff');\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"主题色选择\" size=\"small\">\n <Space>\n <Text>选择主题色:</Text>\n <ColorPicker\n value={color}\n onChange={(color) => setColor(color.toHexString())}\n showText\n />\n </Space>\n </Card>\n <PureGlobal themeToken={{ colorPrimary: color }}>\n <ThemeExample themeToken={{ colorPrimary: color }} />\n </PureGlobal>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n},{\n title: `全局状态管理`,\n description: `展示了 useGlobalContext、SetGlobal、GetGlobal 的使用`,\n code: `const { PureGlobal, useGlobalContext, SetGlobal, GetGlobal } = _Global;\nconst { Space, Button, Input, Card, Typography, Divider } = antd;\n\nconst { Text } = Typography;\n\nconst GlobalContextExample = () => {\n const { global: userName, setGlobal: setUserName } = useGlobalContext('userName');\n const { global: userCount, setGlobal: setUserCount } = useGlobalContext('userCount');\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"全局状态管理 - 用户信息\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>用户名:</Text>\n <Text>{userName || '未设置'}</Text>\n </div>\n <div>\n <Text strong>用户数量:</Text>\n <Text>{userCount || 0}</Text>\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <Space>\n <Button\n onClick={() => setUserName('张三')}\n disabled={userName === '张三'}\n >\n 设置用户名为\"张三\"\n </Button>\n <Button\n onClick={() => setUserName('李四')}\n disabled={userName === '李四'}\n >\n 设置用户名为\"李四\"\n </Button>\n <Button\n onClick={() => setUserName('')}\n >\n 清空用户名\n </Button>\n </Space>\n <Space>\n <Button\n onClick={() => setUserCount((userCount || 0) + 1)}\n >\n 用户数量 +1\n </Button>\n <Button\n onClick={() => setUserCount(0)}\n disabled={userCount === 0}\n >\n 重置用户数量\n </Button>\n </Space>\n </Space>\n </Card>\n\n <SetGlobal globalKey=\"appName\" value=\"Components-Core 示例应用\">\n {({ global: appName }) => (\n <Card title=\"使用 SetGlobal 组件\" size=\"small\">\n <Text>应用名称:{appName}</Text>\n </Card>\n )}\n </SetGlobal>\n\n <GetGlobal globalKey=\"userName\">\n {({ value }) => (\n <Card title=\"使用 GetGlobal 组件\" size=\"small\">\n <Text>当前用户名:{value || '未设置'}</Text>\n </Card>\n )}\n </GetGlobal>\n\n <Card title=\"说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n useGlobalContext Hook 提供了全局状态管理功能,状态保存在 Global 组件一级,\n 不会随着组件销毁而销毁。适合用于需要在多个组件间共享的状态。\n </Text>\n <Text type=\"secondary\">\n SetGlobal 和 GetGlobal 组件提供了更声明式的方式来设置和获取全局值,\n 特别适合在 JSX 中直接使用。\n </Text>\n </Space>\n </Card>\n </Space>\n );\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal>\n <GlobalContextExample />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n},{\n title: `初始化加载`,\n description: `展示了 init 方法的使用,用于系统首次加载时的异步操作`,\n code: `const { PureGlobal } = _Global;\nconst { Space, Card, Typography, Alert, Spin, Button } = antd;\n\nconst { Title, Text } = Typography;\n\nconst InitExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"初始化加载演示\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n 点击下方按钮查看初始化加载效果。init 方法会在系统首次加载时执行,\n 可以返回 Promise 来处理异步操作,在加载完成前不会显示页面内容。\n </Text>\n <Space>\n <Button type=\"primary\" onClick={() => window.location.reload()}>\n 重新加载页面\n </Button>\n </Space>\n </Space>\n </Card>\n\n <Card title=\"模拟的异步数据加载\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>用户信息:</Text>\n <div style={{ marginTop: '8px', padding: '12px', backgroundColor: '#fafafa', borderRadius: '4px' }}>\n <div>用户ID:10001</div>\n <div>用户名:张三</div>\n <div>部门:技术部</div>\n </div>\n </div>\n <div>\n <Text strong>系统配置:</Text>\n <div style={{ marginTop: '8px', padding: '12px', backgroundColor: '#fafafa', borderRadius: '4px' }}>\n <div>主题色:#4096ff</div>\n <div>语言:zh-CN</div>\n <div>环境:production</div>\n </div>\n </div>\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n init 方法会在应用初始化时执行,通常用于加载用户信息、系统配置、权限数据等。\n 在 init 方法返回的 Promise resolve 之前,页面会显示加载状态,不会渲染子组件。\n </Text>\n <Text type=\"secondary\">\n 这样可以确保在页面显示前,所有必要的全局数据都已经加载完成,\n 避免页面出现闪烁或需要数据时的加载等待状态。\n </Text>\n <Alert\n message=\"注意:实际使用时,init 方法应该返回真实的异步请求 Promise\"\n type=\"info\"\n showIcon\n />\n </Space>\n </Card>\n </Space>\n );\n};\n\n// 模拟的 init 方法\nconst mockInit = () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log('初始化完成:加载用户数据和系统配置');\n resolve();\n }, 1500);\n });\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal init={mockInit}>\n <InitExample />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n},{\n title: `警告提示`,\n description: `展示了警告提示的覆盖样式`,\n code: `const { PureGlobal } = _Global;\nconst { Alert, Space } = antd;\nconst { default: Icon } = icon;\n\nconst BasicExample = () => {\n return (\n <PureGlobal>\n <Space direction=\"vertical\">\n <Alert message=\"这是一条操作成功的状态反馈\" type=\"success\" showIcon />\n <Alert message=\"这是一条普通的信息说明\" type=\"info\" showIcon />\n <Alert message=\"这是一条提示信息\" type=\"warning\" showIcon />\n <Alert message=\"这是一条请求失败的状态反馈\" type=\"error\" showIcon />\n <Alert\n message=\"这是一条警示信息\"\n type=\"error\"\n showIcon\n icon={<Icon colorful type=\"icon-color-caisejingshi\" />}\n />\n\n <Alert\n message=\"这是一条操作成功的状态反馈\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"success\"\n showIcon\n />\n <Alert\n message=\"这是一条普通的信息说明\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"info\"\n showIcon\n />\n <Alert\n message=\"这是一条提示信息\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"warning\"\n showIcon\n />\n <Alert\n message=\"这是一条请求失败的状态反馈\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"error\"\n showIcon\n />\n <Alert\n message=\"这是一条警示信息\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"error\"\n showIcon\n icon={<Icon colorful type=\"icon-color-caisejingshi\" />}\n />\n\n <Alert\n message=\"这是一条操作成功的状态反馈\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"success\"\n showIcon\n closable\n />\n <Alert\n message=\"这是一条普通的信息说明\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"info\"\n showIcon\n closable\n />\n <Alert\n message=\"这是一条提示信息\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"warning\"\n showIcon\n closable\n />\n <Alert\n message=\"这是一条请求失败的状态反馈\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"error\"\n showIcon\n closable\n />\n <Alert\n message=\"这是一条警示信息\"\n description=\"提示提示提示提示提示提示提示提示提示\"\n type=\"error\"\n showIcon\n closable\n icon={<Icon colorful type=\"icon-color-caisejingshi\" />}\n />\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BasicExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n},{\n name: \"icon\",\n packageName: \"@components/Icon\",\n component: component_54\n}]\n},{\n title: `按钮`,\n description: `展示了按钮的覆盖样式`,\n code: `const { PureGlobal } = _Global;\nconst { Button, Typography, Space } = antd;\nconst { default: Icon } = icon;\n\nconst BaseExample = () => {\n return (\n <PureGlobal>\n <Space direction=\"vertical\">\n <Space>\n <Button size=\"large\">大按钮</Button>\n <Button>默认按钮</Button>\n <Button size=\"small\">小按钮</Button>\n </Space>\n <Space>\n <Button type=\"primary\">按钮</Button>\n <Button type=\"link\">按钮</Button>\n <Button type=\"text\">按钮</Button>\n </Space>\n <Space>\n <Button danger>危险按钮</Button>\n <Button type=\"primary\" danger>\n 危险按钮\n </Button>\n <Button type=\"link\" danger>\n 危险按钮\n </Button>\n <Button type=\"text\" danger>\n 危险按钮\n </Button>\n </Space>\n <Space>\n <Button disabled>禁用按钮</Button>\n <Button type=\"primary\" danger disabled>\n 禁用危险按钮\n </Button>\n <Button type=\"link\" disabled>\n 禁用Link按钮\n </Button>\n <Button type=\"text\" disabled>\n 禁用Text按钮\n </Button>\n </Space>\n <Space>\n <Button type=\"text\" icon={<Icon type=\"icon-tianjia\" />}>\n 图标按钮\n </Button>\n <Button type=\"text\">\n 图标按钮右\n <Icon type=\"icon-arrow-thin-down\" />\n </Button>\n </Space>\n <Space>\n <Button type=\"primary\" icon={<Icon type=\"icon-tianjia\" />} />\n <Button icon={<Icon type=\"icon-tianjia\" />} />\n <Button danger icon={<Icon type=\"icon-tianjia\" />} />\n <Button type=\"link\" icon={<Icon type=\"icon-tianjia\" />} />\n <Button type=\"text\" icon={<Icon type=\"icon-tianjia\" />} />\n </Space>\n <Space>\n <Button type=\"primary\" disabled icon={<Icon type=\"icon-tianjia\" />} />\n <Button disabled icon={<Icon type=\"icon-tianjia\" />} />\n <Button disabled danger icon={<Icon type=\"icon-tianjia\" />} />\n <Button disabled type=\"link\" icon={<Icon type=\"icon-tianjia\" />} />\n <Button disabled type=\"text\" icon={<Icon type=\"icon-tianjia\" />} />\n </Space>\n <Space>\n <Typography.Link>Link文字</Typography.Link>\n <Typography.Text className=\"ant-btn\">文字</Typography.Text>\n <Typography.Link>\n <Icon type=\"icon-tianjia\" />\n Link文字\n </Typography.Link>\n <Typography.Text className=\"ant-btn\">\n <Icon type=\"icon-tianjia\" />\n 文字\n </Typography.Text>\n <Typography.Link className=\"ant-btn-dangerous\">\n Link文字\n </Typography.Link>\n </Space>\n <Space>\n <Button className=\"btn-no-padding\" type=\"link\" size=\"large\">\n 大按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"link\">\n 默认按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"link\" size=\"small\">\n 小按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"text\" size=\"large\">\n 大按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"text\">\n 默认按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"text\" size=\"small\">\n 小按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"link\" size=\"large\" danger>\n 大按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"link\" danger>\n 默认按钮\n </Button>\n <Button className=\"btn-no-padding\" type=\"link\" size=\"small\" danger>\n 小按钮\n </Button>\n </Space>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n},{\n name: \"icon\",\n packageName: \"@components/Icon\",\n component: component_54\n}]\n},{\n title: `无边框标签`,\n description: `展示了无边框标签`,\n code: `const { PureGlobal } = _Global;\nconst { Tag, Space } = antd;\n\nconst BasicExample = () => {\n return (\n <PureGlobal>\n <Space>\n <Tag className=\"no-border\" closable>\n 标签1\n </Tag>\n <Tag className=\"no-border\" closable>\n 标签2\n </Tag>\n <Tag className=\"no-border\" closable>\n 标签3\n </Tag>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BasicExample />);\n\n`,\n scope: [{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_52\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_53\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_60 from '@components/HelperGuide';\nimport * as component_61 from '@components/Global';\nimport * as component_62 from 'antd';\nimport * as component_63 from '@components/FormInfo';\nimport * as component_64 from '@components/Modal';\nconst readmeConfig = {\n name: `HelperGuide`,\n summary: `<p>HelperGuide 是一个轻量级的帮助文档提示组件,用于在页面上显示帮助说明和可选的帮助链接。它采用图标+文字的形式,样式简洁,适用于在表单、配置页面等场景中为用户提供操作指引或功能说明。</p>\n<p><strong>核心特性</strong></p>\n<ul>\n<li><strong>简洁设计</strong>:采用图标+文字的展示形式,占用空间小,不干扰主要内容</li>\n<li><strong>可配置性</strong>:通过全局枚举配置帮助内容,支持多语言</li>\n<li><strong>灵活展示</strong>:支持仅显示帮助内容,或显示帮助内容+链接</li>\n<li><strong>样式可定制</strong>:支持自定义类名,方便调整样式</li>\n</ul>\n<p><strong>适用场景</strong></p>\n<ul>\n<li>表单字段说明:在复杂表单中为特定字段提供帮助提示</li>\n<li>功能指引:在配置页面或设置页面提供操作说明</li>\n<li>文档链接:提供相关文档的快速访问入口</li>\n<li>提示信息:显示注意事项、使用建议等提示信息</li>\n</ul>`,\n \n \n api: `<h3>HelperGuide</h3>\n<p>HelperGuide 组件用于给用户提供帮助文档提示,显示帮助内容和可选的帮助链接。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>帮助文档的标识符,用于从枚举中获取对应的帮助信息</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义类名</td>\n</tr>\n</tbody>\n</table>\n<h4>枚举配置</h4>\n<p>HelperGuide 组件通过 preset.enums.helperGuide 配置帮助文档内容,该配置应该是一个函数,返回帮助文档数组。</p>\n<table>\n<thead>\n<tr>\n<th>字段名</th>\n<th>类型</th>\n<th>必填</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>string</td>\n<td>是</td>\n<td>帮助文档的标识符,对应 HelperGuide 组件的 name 属性</td>\n</tr>\n<tr>\n<td>content</td>\n<td>string</td>\n<td>是</td>\n<td>帮助文档的内容文字</td>\n</tr>\n<tr>\n<td>url</td>\n<td>string</td>\n<td>否</td>\n<td>帮助文档的链接地址,如果提供则显示\"查看帮助\"链接</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: `HelperGuide_4e237`,\n style: `.HelperGuide_4e237 .helper-guide-custom {\n background: #f0f5ff;\n border: 1px solid #adc6ff;\n}\n.HelperGuide_4e237 .helper-guide-custom .inner {\n background: transparent;\n color: #2f54eb;\n}\n.HelperGuide_4e237 .helper-guide-warning {\n background: #fffbe6;\n border: 1px solid #ffe58f;\n}\n.HelperGuide_4e237 .helper-guide-warning .inner {\n background: transparent;\n color: #faad14;\n}\n.HelperGuide_4e237 .helper-guide-error {\n background: #fff2f0;\n border: 1px solid #ffccc7;\n}\n.HelperGuide_4e237 .helper-guide-error .inner {\n background: transparent;\n color: #ff4d4f;\n}`,\n list: [{\n title: `基础用法`,\n description: `展示不带链接的简单帮助提示`,\n code: `const { default: HelperGuide } = _HelperGuide;\nconst { PureGlobal } = Global;\nconst { Space, Typography, Card } = antd;\n\nconst { Title, Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"username\",\n content: \"请输入有效的用户名,长度为4-20个字符\"\n },\n {\n value: \"password\",\n content: \"密码必须包含字母、数字和特殊字符,长度为8-30个字符\"\n }\n ]\n }\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"表单字段说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>用户名:</Text>\n <HelperGuide name=\"username\" />\n </div>\n <div>\n <Text strong>密码:</Text>\n <HelperGuide name=\"password\" />\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 基础用法:只显示帮助内容,不显示链接。适用于简单的提示信息。\n </Text>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_HelperGuide\",\n packageName: \"@components/HelperGuide\",\n component: component_60\n},{\n name: \"Global\",\n packageName: \"@components/Global\",\n component: component_61\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_62\n}]\n},{\n title: `带帮助链接`,\n description: `展示带帮助链接的提示,可跳转到文档页面`,\n code: `const { default: HelperGuide } = _HelperGuide;\nconst { PureGlobal } = Global;\nconst { Space, Typography, Card } = antd;\n\nconst { Text } = Typography;\n\nconst LinkExample = () => {\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"api-doc\",\n content: \"查看 API 接口文档,了解详细的接口定义和使用说明\",\n url: \"https://example.com/api-docs\"\n },\n {\n value: \"quick-start\",\n content: \"快速开始指南,帮助您快速上手使用系统\",\n url: \"https://example.com/quick-start\"\n }\n ]\n }\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"带帮助链接的提示\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>API 文档:</Text>\n <HelperGuide name=\"api-doc\" />\n </div>\n <div>\n <Text strong>快速开始:</Text>\n <HelperGuide name=\"quick-start\" />\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 当配置中包含 url 字段时,HelperGuide 会显示\"查看帮助\"链接,\n 点击后可以在新窗口打开对应的帮助文档。\n </Text>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<LinkExample />);\n\n`,\n scope: [{\n name: \"_HelperGuide\",\n packageName: \"@components/HelperGuide\",\n component: component_60\n},{\n name: \"Global\",\n packageName: \"@components/Global\",\n component: component_61\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_62\n}]\n},{\n title: `多个帮助提示`,\n description: `展示在同一页面中使用多个 HelperGuide 组件`,\n code: `const { default: HelperGuide } = _HelperGuide;\nconst { PureGlobal } = Global;\nconst { Space, Typography, Card, Divider } = antd;\n\nconst { Title, Text } = Typography;\n\nconst MultipleExample = () => {\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"user-profile\",\n content: \"用户个人信息配置,包括基本资料和联系方式\",\n url: \"https://example.com/docs/user-profile\"\n },\n {\n value: \"security-settings\",\n content: \"安全设置包括密码修改、两步验证等安全功能配置\"\n },\n {\n value: \"notification-preferences\",\n content: \"通知偏好设置,控制接收哪些类型的通知消息\"\n },\n {\n value: \"data-privacy\",\n content: \"数据隐私设置,管理个人数据的访问权限和使用方式\",\n url: \"https://example.com/docs/privacy\"\n }\n ]\n }\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"用户设置页面\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Title level={5}>个人信息</Title>\n <HelperGuide name=\"user-profile\" />\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <div>\n <Title level={5}>安全设置</Title>\n <HelperGuide name=\"security-settings\" />\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <div>\n <Title level={5}>通知设置</Title>\n <HelperGuide name=\"notification-preferences\" />\n </div>\n <Divider style={{ margin: '12px 0' }} />\n <div>\n <Title level={5}>隐私设置</Title>\n <HelperGuide name=\"data-privacy\" />\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 可以在同一个页面中使用多个 HelperGuide 组件,每个组件通过 name 属性\n 引用不同的帮助内容。这种方式特别适合在配置页面、设置页面等多字段场景中使用。\n </Text>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<MultipleExample />);\n\n`,\n scope: [{\n name: \"_HelperGuide\",\n packageName: \"@components/HelperGuide\",\n component: component_60\n},{\n name: \"Global\",\n packageName: \"@components/Global\",\n component: component_61\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_62\n}]\n},{\n title: `自定义样式`,\n description: `展示通过 className 属性自定义组件样式`,\n code: `const { default: HelperGuide } = _HelperGuide;\nconst { PureGlobal } = Global;\nconst { Space, Typography, Card } = antd;\n\nconst { Text } = Typography;\n\nconst CustomStyleExample = () => {\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"normal-style\",\n content: \"默认样式的帮助提示\"\n },\n {\n value: \"custom-color\",\n content: \"蓝色背景的自定义帮助提示\"\n },\n {\n value: \"custom-warning\",\n content: \"黄色警告样式的帮助提示\"\n },\n {\n value: \"custom-error\",\n content: \"红色错误样式的帮助提示\"\n },\n {\n value: \"custom-spacing\",\n content: \"自定义间距的帮助提示\"\n }\n ]\n }\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"自定义样式示例\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>默认样式:</Text>\n <HelperGuide name=\"normal-style\" />\n </div>\n <div style={{ marginTop: '16px' }}>\n <Text strong>蓝色自定义样式:</Text>\n <HelperGuide\n name=\"custom-color\"\n className=\"helper-guide-custom\"\n />\n </div>\n <div style={{ marginTop: '16px' }}>\n <Text strong>警告样式:</Text>\n <HelperGuide\n name=\"custom-warning\"\n className=\"helper-guide-warning\"\n />\n </div>\n <div style={{ marginTop: '16px' }}>\n <Text strong>错误样式:</Text>\n <HelperGuide\n name=\"custom-error\"\n className=\"helper-guide-error\"\n />\n </div>\n <div style={{ marginTop: '24px' }}>\n <Text strong>自定义间距:</Text>\n <HelperGuide\n name=\"custom-spacing\"\n style={{ marginTop: '12px', marginBottom: '8px' }}\n />\n <Text type=\"secondary\">(通过 style 属性添加边距)</Text>\n </div>\n </Space>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Text>\n <div>1. 通过 <Text code>className</Text> 属性可以自定义 HelperGuide 的样式,样式应用在外层容器上。</div>\n <div>2. 通过 <Text code>style</Text> 属性可以添加行内样式,如调整间距等。</div>\n <div>3. 自定义样式可以覆盖组件的默认背景色、边框、文字颜色等。</div>\n </Text>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<CustomStyleExample />);\n\n`,\n scope: [{\n name: \"_HelperGuide\",\n packageName: \"@components/HelperGuide\",\n component: component_60\n},{\n name: \"Global\",\n packageName: \"@components/Global\",\n component: component_61\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_62\n}]\n},{\n title: `真实业务场景`,\n description: `展示在员工信息录入表单中的实际应用`,\n code: `const { default: HelperGuide } = _HelperGuide;\nconst { default: FormInfo, Form, SubmitButton, fields } = _FormInfo;\nconst { useModal } = _Modal;\nconst { PureGlobal } = Global;\nconst { Space, Card, Typography } = antd;\n\nconst { Input, Select } = fields;\n\nconst RealScenarioExample = () => {\n const modal = useModal();\n\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"employee-form-employeeId\",\n content: \"员工ID是员工的唯一标识,由系统自动生成,不可修改\"\n },\n {\n value: \"employee-form-department\",\n content: \"请选择员工所属部门,部门决定了员工的权限范围\",\n url: \"https://example.com/docs/departments\"\n },\n {\n value: \"employee-form-email\",\n content: \"邮箱地址用于系统通知和密码找回,请确保邮箱地址有效\"\n },\n {\n value: \"employee-form-phone\",\n content: \"手机号码用于接收短信验证码和紧急通知\"\n },\n {\n value: \"employee-form-hireDate\",\n content: \"入职日期决定了员工的年假计算和试用期时长\"\n }\n ]\n }\n }}\n >\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"员工信息录入\" size=\"small\">\n <Form\n helperGuideName=\"employee-form\"\n onSubmit={(data) => {\n modal({\n title: \"员工信息提交成功\",\n children: <pre>{JSON.stringify(data, null, 2)}</pre>\n });\n }}\n >\n <FormInfo\n list={[\n <Input \n name=\"employeeId\" \n label=\"员工ID\" \n placeholder=\"自动生成\" \n disabled \n />,\n <Select\n name=\"department\"\n label=\"所属部门\"\n rule=\"REQ\"\n options={[\n { label: \"技术部\", value: \"tech\" },\n { label: \"产品部\", value: \"product\" },\n { label: \"运营部\", value: \"operation\" },\n { label: \"人力资源部\", value: \"hr\" }\n ]}\n />,\n <Input \n name=\"email\" \n label=\"邮箱地址\" \n rule=\"REQ EMAIL\"\n placeholder=\"请输入邮箱地址\" \n />,\n <Input \n name=\"phone\" \n label=\"手机号码\" \n rule=\"REQ TEL\"\n placeholder=\"请输入手机号码\" \n />,\n <Input \n name=\"hireDate\" \n label=\"入职日期\" \n rule=\"REQ\"\n type=\"date\"\n />\n ]}\n />\n <SubmitButton \n type=\"primary\" \n style={{ marginRight: 8 }}\n >\n 保存\n </SubmitButton>\n </Form>\n </Card>\n <Card title=\"说明\" size=\"small\">\n <Typography.Text type=\"secondary\">\n 真实业务场景示例:在员工信息录入表单中,为每个字段提供相应的帮助提示,\n 帮助用户理解字段含义和要求。这样可以提高表单填写的准确性和效率。\n </Typography.Text>\n </Card>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<RealScenarioExample />);\n\n`,\n scope: [{\n name: \"_HelperGuide\",\n packageName: \"@components/HelperGuide\",\n component: component_60\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_63\n},{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_64\n},{\n name: \"Global\",\n packageName: \"@components/Global\",\n component: component_61\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_62\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_50 from '@components/HistoryStore';\nimport * as component_51 from 'antd';\nconst readmeConfig = {\n name: `HistoryStore`,\n summary: `<p>HistoryStore 是一个历史记录管理组件,用于保存和展示用户的操作历史记录(如搜索记录、选择记录等)。它利用 localStorage 持久化存储数据,在用户再次访问时可以快速选择历史记录,提升用户体验。</p>\n<p><strong>核心特性</strong></p>\n<ul>\n<li><strong>持久化存储</strong>:基于 localStorage 实现数据持久化,刷新页面后数据不丢失</li>\n<li><strong>多场景支持</strong>:通过 storeName 属性区分不同场景的历史记录,互不干扰</li>\n<li><strong>智能去重</strong>:自动去除重复的历史记录,相同值只会保留最新的一次</li>\n<li><strong>数量限制</strong>:可配置最大保存数量,避免占用过多存储空间</li>\n<li><strong>灵活触发</strong>:支持通过焦点、点击等多种方式触发历史记录展示</li>\n<li><strong>Render Props</strong>:通过 render props 模式提供完整的控制能力,可自定义触发逻辑</li>\n</ul>\n<p><strong>适用场景</strong></p>\n<ul>\n<li>搜索框历史记录:保存用户的搜索关键词,方便快速重新搜索</li>\n<li>下拉框选择历史:保存用户选择过的选项,提供快捷选择入口</li>\n<li>过滤器历史:保存用户设置过的过滤条件,一键应用历史配置</li>\n<li>其他需要记录用户操作历史的场景</li>\n</ul>`,\n \n \n api: `<h3>HistoryStore</h3>\n<p>HistoryStore 组件用于管理用户的历史记录,支持将搜索、选择等操作保存到 localStorage,并在需要时展示历史记录列表供用户快速选择。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义类名</td>\n</tr>\n<tr>\n<td>overlayClassName</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>弹窗内容的自定义类名</td>\n</tr>\n<tr>\n<td>storeName</td>\n<td>string</td>\n<td>否</td>\n<td>'HISTORY_STORE_KEY'</td>\n<td>localStorage 的键名,用于区分不同场景的历史记录</td>\n</tr>\n<tr>\n<td>maxLength</td>\n<td>number</td>\n<td>否</td>\n<td>5</td>\n<td>最多保存的历史记录数量,为 0 时不限制</td>\n</tr>\n<tr>\n<td>label</td>\n<td>string</td>\n<td>否</td>\n<td>'最近搜索'</td>\n<td>历史记录列表的标题文字</td>\n</tr>\n<tr>\n<td>children</td>\n<td>function</td>\n<td>是</td>\n<td>-</td>\n<td>子组件,接收 render props</td>\n</tr>\n<tr>\n<td>onSelect</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>选中历史记录时的回调函数,接收参数:(value, item)</td>\n</tr>\n<tr>\n<td>zIndex</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n<td>弹窗的 z-index 层级</td>\n</tr>\n<tr>\n<td>getPopupContainer</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>获取弹窗容器的函数</td>\n</tr>\n</tbody>\n</table>\n<h4>Render Props</h4>\n<p>children 是一个函数,接收以下参数:</p>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>类型</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>open</td>\n<td>boolean</td>\n<td>弹窗是否打开</td>\n</tr>\n<tr>\n<td>openHistory</td>\n<td>function</td>\n<td>打开历史记录弹窗的方法</td>\n</tr>\n<tr>\n<td>appendHistory</td>\n<td>function</td>\n<td>添加历史记录的方法,参数:{value, label}</td>\n</tr>\n<tr>\n<td>setOnSelect</td>\n<td>function</td>\n<td>设置选中回调的方法,参数:callback</td>\n</tr>\n<tr>\n<td>close</td>\n<td>function</td>\n<td>关闭弹窗的方法</td>\n</tr>\n</tbody>\n</table>\n<h4>历史记录数据格式</h4>\n<p>每条历史记录是一个对象,包含以下字段:</p>\n<table>\n<thead>\n<tr>\n<th>字段名</th>\n<th>类型</th>\n<th>必填</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>string</td>\n<td>是</td>\n<td>历史记录的值</td>\n</tr>\n<tr>\n<td>label</td>\n<td>string</td>\n<td>是</td>\n<td>历史记录的显示文本</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `搜索框历史记录`,\n description: `展示基础用法,搜索框获取焦点时显示历史记录`,\n code: `const { default: HistoryStore } = _HistoryStore;\nconst { Input, Space, Card, Typography } = antd;\n\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"搜索框历史记录\" size=\"small\">\n <HistoryStore\n onSelect={(value, item) => {\n console.log('选中历史记录:', value, item);\n }}\n >\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"输入关键词搜索\"\n allowClear\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n 基础用法:搜索框获取焦点时显示历史记录,点击历史记录标签或回车搜索后,\n 该记录会被保存到历史记录中。\n </Text>\n <Text type=\"secondary\">\n 历史记录使用 localStorage 持久化存储,刷新页面后仍然可用。\n </Text>\n </Space>\n </Card>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_HistoryStore\",\n packageName: \"@components/HistoryStore\",\n component: component_50\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_51\n}]\n},{\n title: `自定义配置`,\n description: `展示 maxLength、label 等配置属性的用法`,\n code: `const { default: HistoryStore } = _HistoryStore;\nconst { Input, Space, Card, Typography, Divider } = antd;\n\nconst { Text } = Typography;\n\nconst CustomConfigExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"自定义配置示例\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>默认配置(最多5条,标题\"最近搜索\"):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore>\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"输入关键词\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '16px 0' }} />\n\n <div>\n <Text strong>自定义最大数量(最多10条):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore maxLength={10}>\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"输入关键词\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '16px 0' }} />\n\n <div>\n <Text strong>自定义标题(\"搜索历史\"):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore label=\"搜索历史\">\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"输入关键词\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '16px 0' }} />\n\n <div>\n <Text strong>不限制数量(maxLength={0}):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore maxLength={0}>\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"输入关键词\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 通过 maxLength、label 等属性可以自定义历史记录的配置。\n maxLength 为 0 时不限制保存数量,但建议设置合理的最大值以避免占用过多存储空间。\n </Text>\n </Card>\n </Space>\n );\n};\n\nrender(<CustomConfigExample />);\n\n`,\n scope: [{\n name: \"_HistoryStore\",\n packageName: \"@components/HistoryStore\",\n component: component_50\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_51\n}]\n},{\n title: `Select 组件历史记录`,\n description: `展示与 Select 组件结合使用,记录选择历史`,\n code: `const { default: HistoryStore } = _HistoryStore;\nconst { Select, Space, Card, Typography, Input } = antd;\n\nconst { Text } = Typography;\n\nconst SelectExample = () => {\n const departmentOptions = [\n { label: '技术部', value: 'tech' },\n { label: '产品部', value: 'product' },\n { label: '运营部', value: 'operation' },\n { label: '市场部', value: 'marketing' },\n { label: '人力资源部', value: 'hr' },\n { label: '财务部', value: 'finance' }\n ];\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"Select 组件历史记录\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>部门选择:</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"department_history\"\n label=\"最近选择的部门\"\n >\n {({ appendHistory, openHistory, close, open }) => (\n <Select\n placeholder=\"选择部门\"\n style={{ width: '100%' }}\n options={departmentOptions}\n open={open}\n onDropdownVisibleChange={(visible) => {\n if (visible) {\n openHistory();\n } else {\n close();\n }\n }}\n onSelect={(value, option) => {\n appendHistory({\n value,\n label: option.label\n });\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <div style={{ marginTop: 16 }}>\n <Text strong>城市选择:</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"city_history\"\n label=\"最近选择的城市\"\n >\n {({ appendHistory, openHistory, close, open }) => (\n <Select\n mode=\"tags\"\n placeholder=\"选择或输入城市\"\n style={{ width: '100%' }}\n options={[\n { label: '北京', value: 'beijing' },\n { label: '上海', value: 'shanghai' },\n { label: '广州', value: 'guangzhou' },\n { label: '深圳', value: 'shenzhen' }\n ]}\n open={open}\n onDropdownVisibleChange={(visible) => {\n if (visible) {\n openHistory();\n } else {\n close();\n }\n }}\n onChange={(values) => {\n if (values.length > 0) {\n const lastValue = values[values.length - 1];\n const option = [\n { label: '北京', value: 'beijing' },\n { label: '上海', value: 'shanghai' },\n { label: '广州', value: 'guangzhou' },\n { label: '深圳', value: 'shenzhen' }\n ].find(opt => opt.value === lastValue);\n if (option) {\n appendHistory({\n value: lastValue,\n label: option.label\n });\n }\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n HistoryStore 可以与 Select 组件结合使用,记录用户的选择历史。\n 通过 storeName 区分不同的历史记录场景,互不干扰。\n 使用 onDropdownVisibleChange 控制下拉框的打开状态,实现历史记录和选项列表的切换。\n </Text>\n </Card>\n </Space>\n );\n};\n\nrender(<SelectExample />);\n\n`,\n scope: [{\n name: \"_HistoryStore\",\n packageName: \"@components/HistoryStore\",\n component: component_50\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_51\n}]\n},{\n title: `多个独立存储`,\n description: `展示通过不同 storeName 创建多个独立的历史记录`,\n code: `const { default: HistoryStore } = _HistoryStore;\nconst { Input, Select, Space, Card, Typography, Divider } = antd;\n\nconst { Text } = Typography;\n\nconst MultipleStoresExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"多个独立的历史记录存储\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>用户搜索(storeName: user_search):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"user_search\"\n label=\"最近搜索的用户\"\n maxLength={5}\n >\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"搜索用户名或手机号\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '12px 0' }} />\n\n <div>\n <Text strong>订单搜索(storeName: order_search):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"order_search\"\n label=\"最近搜索的订单\"\n maxLength={5}\n >\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"搜索订单号或商品名称\"\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '12px 0' }} />\n\n <div>\n <Text strong>部门筛选(storeName: department_filter):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"department_filter\"\n label=\"最近筛选的部门\"\n maxLength={3}\n >\n {({ appendHistory, openHistory, close, open }) => (\n <Select\n placeholder=\"选择部门\"\n style={{ width: '100%' }}\n options={[\n { label: '技术部', value: 'tech' },\n { label: '产品部', value: 'product' },\n { label: '运营部', value: 'operation' }\n ]}\n open={open}\n onDropdownVisibleChange={(visible) => {\n if (visible) {\n openHistory();\n } else {\n close();\n }\n }}\n onSelect={(value, option) => {\n appendHistory({ value, label: option.label });\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n\n <Divider style={{ margin: '12px 0' }} />\n\n <div>\n <Text strong>状态筛选(storeName: status_filter):</Text>\n <div style={{ marginTop: 8 }}>\n <HistoryStore\n storeName=\"status_filter\"\n label=\"最近筛选的状态\"\n maxLength={3}\n >\n {({ appendHistory, openHistory, close, open }) => (\n <Select\n placeholder=\"选择状态\"\n style={{ width: '100%' }}\n options={[\n { label: '待处理', value: 'pending' },\n { label: '处理中', value: 'processing' },\n { label: '已完成', value: 'completed' },\n { label: '已取消', value: 'cancelled' }\n ]}\n open={open}\n onDropdownVisibleChange={(visible) => {\n if (visible) {\n openHistory();\n } else {\n close();\n }\n }}\n onSelect={(value, option) => {\n appendHistory({ value, label: option.label });\n }}\n />\n )}\n </HistoryStore>\n </div>\n </div>\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 通过不同的 storeName 可以创建多个独立的历史记录存储,每个存储互不干扰。\n 这样可以在同一个页面中使用多个 HistoryStore 组件,分别记录不同操作的历史记录。\n 常用于多个搜索框、多个筛选器等场景。\n </Text>\n </Card>\n </Space>\n );\n};\n\nrender(<MultipleStoresExample />);\n\n`,\n scope: [{\n name: \"_HistoryStore\",\n packageName: \"@components/HistoryStore\",\n component: component_50\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_51\n}]\n},{\n title: `真实业务场景`,\n description: `展示在订单管理页面中的实际应用`,\n code: `const { default: HistoryStore } = _HistoryStore;\nconst { Input, Select, Button, Space, Table, Card, Typography, Tag } = antd;\n\nconst { Text } = Typography;\n\nconst RealScenarioExample = () => {\n const [filters, setFilters] = React.useState({});\n\n const columns = [\n {\n title: '订单号',\n dataIndex: 'orderNo',\n key: 'orderNo'\n },\n {\n title: '客户姓名',\n dataIndex: 'customerName',\n key: 'customerName'\n },\n {\n title: '金额',\n dataIndex: 'amount',\n key: 'amount',\n render: (amount) => \\`¥\\${amount}\\`\n },\n {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status) => {\n const statusMap = {\n pending: <Tag color=\"orange\">待处理</Tag>,\n processing: <Tag color=\"blue\">处理中</Tag>,\n completed: <Tag color=\"green\">已完成</Tag>,\n cancelled: <Tag color=\"red\">已取消</Tag>\n };\n return statusMap[status] || status;\n }\n },\n {\n title: '创建时间',\n dataIndex: 'createTime',\n key: 'createTime'\n }\n ];\n\n const mockData = [\n {\n key: '1',\n orderNo: 'ORD202401001',\n customerName: '张三',\n amount: 1200.00,\n status: 'completed',\n createTime: '2024-01-15 10:30:00'\n },\n {\n key: '2',\n orderNo: 'ORD202401002',\n customerName: '李四',\n amount: 3500.00,\n status: 'processing',\n createTime: '2024-01-15 11:20:00'\n },\n {\n key: '3',\n orderNo: 'ORD202401003',\n customerName: '王五',\n amount: 890.00,\n status: 'pending',\n createTime: '2024-01-15 14:45:00'\n }\n ];\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"订单管理页面\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space wrap>\n <div>\n <Text>订单搜索:</Text>\n <HistoryStore\n storeName=\"order_search\"\n label=\"最近搜索的订单\"\n maxLength={5}\n >\n {({ appendHistory, openHistory }) => (\n <Input.Search\n placeholder=\"搜索订单号或客户姓名\"\n style={{ width: 280 }}\n onFocus={openHistory}\n onSearch={(value) => {\n if (value) {\n setFilters({ ...filters, keyword: value });\n appendHistory({ value, label: value });\n }\n }}\n />\n )}\n </HistoryStore>\n </div>\n\n <div>\n <Text>状态:</Text>\n <HistoryStore\n storeName=\"order_status_filter\"\n label=\"最近筛选的状态\"\n maxLength={3}\n >\n {({ appendHistory, openHistory, close, open }) => (\n <Select\n placeholder=\"选择状态\"\n style={{ width: 150 }}\n allowClear\n options={[\n { label: '待处理', value: 'pending' },\n { label: '处理中', value: 'processing' },\n { label: '已完成', value: 'completed' },\n { label: '已取消', value: 'cancelled' }\n ]}\n open={open}\n onDropdownVisibleChange={(visible) => {\n if (visible) {\n openHistory();\n } else {\n close();\n }\n }}\n onSelect={(value, option) => {\n setFilters({ ...filters, status: value });\n appendHistory({ value, label: option.label });\n }}\n onClear={() => {\n setFilters({ ...filters, status: undefined });\n }}\n />\n )}\n </HistoryStore>\n </div>\n\n <Button type=\"primary\">查询</Button>\n <Button>重置</Button>\n </Space>\n\n <div style={{ marginTop: 16 }}>\n <Text type=\"secondary\" style={{ fontSize: 12 }}>\n 当前筛选条件:{Object.keys(filters).length > 0 ? JSON.stringify(filters) : '无'}\n </Text>\n </div>\n\n <Table\n columns={columns}\n dataSource={mockData}\n pagination={false}\n size=\"small\"\n />\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Text type=\"secondary\">\n 真实业务场景示例:在订单管理页面中,使用两个独立的 HistoryStore 组件,\n 分别记录订单搜索历史和状态筛选历史。这样用户可以快速选择之前的搜索条件,\n 提高操作效率。通过不同的 storeName 确保两个历史记录互不干扰。\n </Text>\n </Card>\n </Space>\n );\n};\n\nrender(<RealScenarioExample />);\n\n`,\n scope: [{\n name: \"_HistoryStore\",\n packageName: \"@components/HistoryStore\",\n component: component_50\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_51\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_55 from '@kne/react-icon';\nimport * as component_56 from 'antd';\nimport * as component_57 from '@kne/react-fetch';\nimport * as component_58 from 'axios';\nimport * as component_59 from '@kne/remote-loader';\nconst readmeConfig = {\n name: `react-icon`,\n summary: `<h3>Iconfont</h3>\n<p><code>Iconfont</code> 是一个基于字体图标的 React 组件,支持两种模式:</p>\n<ul>\n<li><strong>单色模式</strong>:使用传统字体图标渲染</li>\n<li><strong>多彩模式</strong>:通过 SVG 方式渲染彩色图标</li>\n</ul>\n<h4>基础图标</h4>\n<pre><code class=\"language-jsx\"><Iconfont type=\"user\" />\n</code></pre>\n<h4>指定尺寸</h4>\n<pre><code class=\"language-jsx\"><Iconfont type=\"search\" size={24} />\n</code></pre>\n<h4>多彩图标模式</h4>\n<pre><code class=\"language-jsx\"><Iconfont type=\"feedback\" colorful />\n</code></pre>\n<h4>注意事项</h4>\n<ol>\n<li>需要预先引入对应的字体文件/CSS</li>\n<li>多彩模式需要确保 SVG 资源可用</li>\n<li>组件会自动处理 <code>icon-</code> 前缀(无需手动添加)</li>\n</ol>\n<p><strong>以上资源可以通过<code>FontLoader</code>进行加载</strong></p>\n<h3>FontLoader</h3>\n<p><code>FontLoader</code> 是一个用于动态加载/卸载字体资源的 React 组件,具有以下特性:</p>\n<ul>\n<li>按需加载字体文件</li>\n<li>自动卸载机制(组件卸载时)</li>\n<li>纯逻辑组件(无UI渲染)</li>\n</ul>\n<h4>加载本地字体</h4>\n<pre><code class=\"language-jsx\"><FontLoader \n path=\"../assets/fonts/iconfont.woff\" \n name=\"app-iconfont\"\n/>\n</code></pre>\n<h4>加载CDN字体</h4>\n<pre><code class=\"language-jsx\"><FontLoader\n path=\"https://cdn.example.com/fonts/iconfont.woff2\"\n name=\"cdn-iconfont\"\n/>\n</code></pre>\n<h4>注意事项</h4>\n<ol>\n<li>需要配合 <code>@font-face</code> CSS 规则使用</li>\n<li>字体名称(<code>name</code>)需与CSS定义保持一致</li>\n<li>建议在应用根组件或路由组件中使用</li>\n<li>多次加载同名字体时会自动去重</li>\n</ol>\n<h3>loadFont</h3>\n<p>该函数提供了动态加载字体资源的功能,主要包含两个实用函数:</p>\n<ol>\n<li>\n<p><strong>路径处理函数</strong> - <code>getLastFolderName</code></p>\n<ul>\n<li>从文件路径中提取最后一个非空文件夹名</li>\n<li>自动处理路径末尾的冗余斜杠</li>\n</ul>\n</li>\n<li>\n<p><strong>字体加载函数</strong> - <code>loadFont</code></p>\n<ul>\n<li>智能避免重复加载相同字体</li>\n<li>支持通过JS脚本方式加载字体资源</li>\n<li>自动使用路径最后一段作为默认字体名称</li>\n</ul>\n</li>\n</ol>\n<h4>基本用法</h4>\n<pre><code class=\"language-javascript\">import { loadFont } from './loadFont';\n\n// 加载字体(自动使用路径最后一段作为名称)\nawait loadFont('/assets/fonts/roboto/roboto.js');\n\n// 指定字体名称\nawait loadFont('/assets/fonts/roboto/main.js', 'Roboto');\n</code></pre>\n<h4>实现特点</h4>\n<ol>\n<li><strong>防重复加载</strong>:通过检查head中是否已存在相同href的script标签</li>\n<li><strong>路径标准化</strong>:自动处理路径末尾的冗余斜杠</li>\n<li><strong>容错处理</strong>:过滤路径中的空字符串部分</li>\n</ol>\n<h4>注意事项</h4>\n<ol>\n<li>当前仅支持通过.js文件加载字体</li>\n<li>需要确保字体JS文件符合标准格式</li>\n<li>在浏览器环境中使用,依赖document对象</li>\n</ol>`,\n \n \n api: `<h3>Iconfont</h3>\n<table>\n<thead>\n<tr>\n<th>属性</th>\n<th>类型</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>type</code></td>\n<td>string</td>\n<td><strong>必填</strong></td>\n<td>图标名称(如 <code>'home'</code>)</td>\n</tr>\n<tr>\n<td><code>colorful</code></td>\n<td>boolean</td>\n<td><code>false</code></td>\n<td>是否启用多彩模式</td>\n</tr>\n<tr>\n<td><code>className</code></td>\n<td>string</td>\n<td>-</td>\n<td>自定义 CSS 类名</td>\n</tr>\n<tr>\n<td><code>fontClassName</code></td>\n<td>string</td>\n<td><code>'iconfont'</code></td>\n<td>字体图标基础类名</td>\n</tr>\n<tr>\n<td><code>size</code></td>\n<td>number/string</td>\n<td>-</td>\n<td>图标尺寸(如 <code>20</code> 或 <code>'2em'</code>)</td>\n</tr>\n<tr>\n<td><code>style</code></td>\n<td>object</td>\n<td>-</td>\n<td>行内样式对象</td>\n</tr>\n<tr>\n<td><code>prefix</code></td>\n<td>string</td>\n<td><code>''</code></td>\n<td>图标名前缀(自动处理 <code>icon-</code> 前缀)</td>\n</tr>\n<tr>\n<td><code>...other</code></td>\n<td>any</td>\n<td>-</td>\n<td>其他透传的 DOM 属性</td>\n</tr>\n</tbody>\n</table>\n<h3>FontLoader</h3>\n<table>\n<thead>\n<tr>\n<th>属性</th>\n<th>类型</th>\n<th>必填</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>path</code></td>\n<td>string</td>\n<td>是</td>\n<td>字体文件路径(支持相对/绝对路径)</td>\n</tr>\n<tr>\n<td><code>name</code></td>\n<td>string</td>\n<td>是</td>\n<td>注册的字体名称(用于CSS引用)</td>\n</tr>\n</tbody>\n</table>\n<h3><code>getLastFolderName(path)</code></h3>\n<pre><code class=\"language-javascript\">/**\n * 从文件路径中提取最后一个文件夹名\n * @param {string} path - 文件路径\n * @return {string} 最后一个非空文件夹名\n */\n</code></pre>\n<h3><code>loadFont(path, name)</code></h3>\n<pre><code class=\"language-javascript\">/**\n * 动态加载字体资源\n * @param {string} path - 字体资源路径(.js)\n * @param {string} [name] - 可选字体名称,未提供时使用路径最后一段\n */\n</code></pre>`,\n example: {\n isFull: true,\n className: `react_icon_c6add`,\n style: `.react_icon_c6add .item {\n width: 150px;\n word-break: break-all;\n}\n.react_icon_c6add .item .ant-typography {\n position: relative;\n}\n.react_icon_c6add .item .ant-typography-copy {\n visibility: hidden;\n position: absolute;\n right: -20px;\n}\n.react_icon_c6add .item:hover .ant-typography-copy {\n visibility: visible;\n}`,\n list: [{\n title: `这里填写示例标题`,\n description: `这里填写示例说明`,\n code: `const {default: Icon} = _Icon;\nconst {Slider, Space, Typography} = antd;\nconst {useState} = React;\nconst {createWithFetch} = ReactFetch;\nconst {default: axios} = _axios;\nconst {createWithRemoteLoader} = remoteLoader;\n\nconst BaseExample = createWithRemoteLoader({\n modules: [\"components-iconfont:Font\"],\n})(({remoteModules}) => {\n const [Font] = remoteModules;\n const [value, setValue] = useState(30);\n return (\n <Space direction=\"vertical\">\n <Space>\n <div>调整大小:</div>\n <Slider\n style={{width: 100}}\n max={60}\n min={12}\n value={value}\n onChange={setValue}\n />\n <div>{value}px</div>\n </Space>\n {\n <Font>\n {({list}) => {\n return (\n <Space wrap align=\"top\" size=\"large\">\n {list.map(({name, font_class}) => {\n return (\n <Space\n className=\"item\"\n direction=\"vertical\"\n align=\"center\"\n key={name}\n >\n <Icon type={font_class} size={value}/>\n <Typography.Text\n copyable={{\n text:\n '<Icon type=\"' +\n font_class +\n '\" size={' +\n value +\n \"} />\",\n }}\n >\n {font_class}\n </Typography.Text>\n <div>{name}</div>\n </Space>\n );\n })}\n </Space>\n );\n }}\n </Font>\n }\n </Space>\n );\n});\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Icon\",\n packageName: \"@kne/react-icon\",\n component: component_55\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_56\n},{\n name: \"ReactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_57\n},{\n name: \"_axios\",\n packageName: \"axios\",\n component: component_58\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_59\n}]\n},{\n title: `这里填写示例标题`,\n description: `这里填写示例说明`,\n code: `const { default: Icon } = _Icon;\nconst { Space, Slider, Typography } = antd;\nconst { useState } = React;\nconst { createWithFetch } = ReactFetch;\nconst { createWithRemoteLoader } = remoteLoader;\nconst { default: axios } = _axios;\n\nconst BaseExample = createWithRemoteLoader({\n modules: [\"components-iconfont:ColorfulFont\"],\n})(({ remoteModules }) => {\n const [ColorfulFont] = remoteModules;\n const [value, setValue] = useState(30);\n return (\n <Space direction=\"vertical\">\n <Space>\n <div>调整大小:</div>\n <Slider\n style={{ width: 100 }}\n max={60}\n min={12}\n value={value}\n onChange={setValue}\n />\n <div>{value}px</div>\n </Space>\n <ColorfulFont>\n {({ list }) => (\n <Space wrap align=\"top\" size=\"large\">\n {list.map(({ name }) => {\n return (\n <Space\n className=\"item\"\n direction=\"vertical\"\n align=\"center\"\n key={name}\n >\n <Icon colorful type={name} size={value} />\n <Typography.Text\n copyable={{\n text:\n '<Icon colorful type=\"' +\n name +\n '\" size={' +\n value +\n \"} />\",\n }}\n >\n {name}\n </Typography.Text>\n </Space>\n );\n })}\n </Space>\n )}\n </ColorfulFont>\n </Space>\n );\n});\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Icon\",\n packageName: \"@kne/react-icon\",\n component: component_55\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_56\n},{\n name: \"ReactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_57\n},{\n name: \"_axios\",\n packageName: \"axios\",\n component: component_58\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_59\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_46 from '@components/Image';\nimport * as component_47 from 'antd';\nimport * as component_48 from '@components/Global';\nimport * as component_49 from '@components/Icon';\nconst readmeConfig = {\n name: `Image`,\n summary: `<p>Image 组件是一个增强的图片显示组件,支持两种加载方式:</p>\n<ol>\n<li>通过 src 属性直接加载图片URL</li>\n<li>通过 id 属性从 OSS 服务器加载图片</li>\n</ol>\n<p>组件特性:</p>\n<ul>\n<li>自动加载状态显示和错误处理</li>\n<li>支持 Avatar 头像模式,可显示默认性别图标</li>\n<li>支持自定义加载状态和错误状态组件</li>\n<li>完全兼容原生 img 标签的基本属性</li>\n</ul>\n<p>主要应用场景:</p>\n<ul>\n<li>用户头像展示</li>\n<li>商品图片展示</li>\n<li>文档预览</li>\n<li>需要加载状态的图片显示</li>\n</ul>`,\n \n \n api: `<h3>Image 基础图片组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>src</td>\n<td>图片的src地址</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>id</td>\n<td>oss的id</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>loading</td>\n<td>加载时显示的组件</td>\n<td>ReactNode</td>\n<td><code><Skeleton.Avatar shape=\"square\" active/></code></td>\n</tr>\n<tr>\n<td>error</td>\n<td>加载错误时显示的组件</td>\n<td>ReactNode</td>\n<td><code><Icon role=\"error-icon\" colorful type=\"icon-color-touxiang-nan\"/></code></td>\n</tr>\n<tr>\n<td>alt</td>\n<td>图片的alt属性</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClick</td>\n<td>点击图片的回调函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>API配置,用于加载OSS图片</td>\n<td>object</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>Image.Avatar 头像组件</h3>\n<p>基于Antd的Avatar组件,支持图片头像和默认性别图标头像,其他参数参考Antd的Avatar组件</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>src</td>\n<td>图片的src地址</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>id</td>\n<td>oss的id</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>gender</td>\n<td>性别 F,female,f为女其他为男</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>size</td>\n<td>头像大小</td>\n<td>number</td>\n<td>100</td>\n</tr>\n<tr>\n<td>width</td>\n<td>头像宽度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>height</td>\n<td>头像高度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>shape</td>\n<td>头像形状,可选 'circle'</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>gap</td>\n<td>头像与图标之间的间距</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>icon</td>\n<td>自定义图标</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultAvatar</td>\n<td>默认头像</td>\n<td>string</td>\n<td>默认头像SVG</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>apis</td>\n<td>API配置,用于加载OSS图片</td>\n<td>object</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: `Image_be53a`,\n style: `@charset \"UTF-8\";\n.Image_be53a { /* Image 组件示例样式 */ }\n.Image_be53a .product-card .ant-card-cover {\n height: 180px;\n overflow: hidden;\n}\n.Image_be53a .user-avatar:hover {\n transform: scale(1.05);\n transition: transform 0.3s;\n}\n.Image_be53a .image-preview {\n text-align: center;\n}\n.Image_be53a .image-preview img {\n max-width: 100%;\n border-radius: 4px;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);\n}`,\n list: [{\n title: `基础图片加载`,\n description: `通过src属性直接加载图片`,\n code: `const { default: Image } = _Image;\nconst { Space, Card, Typography } = antd;\n\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"基础图片加载\" size=\"small\">\n <Space direction=\"vertical\">\n <div>\n <Text strong>通过 src 属性加载图片:</Text>\n <div style={{ marginTop: 8 }}>\n <Image src={window.PUBLIC_URL + \"/logo512.png\"} style={{ width: '100px', height: '100px' }} alt=\"Logo图片\" />\n </div>\n </div>\n <div style={{ marginTop: 16 }}>\n <Text strong>通过 URL 加载网络图片:</Text>\n <div style={{ marginTop: 8 }}>\n <Image src=\"https://picsum.photos/seed/example/200/200.jpg\" style={{ width: '100px', height: '100px' }} alt=\"示例图片\" />\n </div>\n </div>\n </Space>\n </Card>\n \n <Card title=\"说明\" size=\"small\">\n <Text>\n <div>1. Image 组件通过 src 属性直接加载图片URL。</div>\n <div>2. 支持本地图片和网络图片加载。</div>\n <div>3. 可以通过 style 属性设置图片大小。</div>\n <div>4. 自动处理加载状态和错误状态。</div>\n </Text>\n </Card>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n}]\n},{\n title: `OSS图片加载`,\n description: `通过id从OSS服务器加载图片,展示加载中和失败状态`,\n code: `const {default: Image} = _Image;\nconst {PureGlobal} = global;\nconst {Space} = antd;\nconst BaseExample = () => {\n return <PureGlobal preset={{\n apis: {\n file: {\n getUrl: {\n loader: ({params}) => {\n if (params.id === 'logo513.png') {\n return new Promise(() => {\n\n });\n }\n return new Promise((resolve) => {\n resolve(window.PUBLIC_URL + '/' + params.id);\n });\n\n }\n }\n }\n }\n }}>\n <Space>\n <Image id=\"logo512.png\" style={{width: '100px', height: '100px'}}/>\n <Image id=\"logo513.png\" style={{width: '100px', height: '100px'}}/>\n <Image id=\"logo511.png\" style={{width: '100px', height: '100px'}}/>\n </Space>\n </PureGlobal>;\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_48\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n}]\n},{\n title: `头像组件`,\n description: `展示Image.Avatar头像组件的各种用法`,\n code: `const { default: Image } = _Image;\nconst { Space } = antd;\nconst BaseExample = () => {\n return (\n <Space>\n <Image.Avatar src={window.PUBLIC_URL + \"/avatar.png\"} shape=\"circle\" />\n <Image.Avatar\n src={window.PUBLIC_URL + \"/avatar.png\"}\n shape=\"circle\"\n size={80}\n />\n <Image.Avatar\n src={window.PUBLIC_URL + \"/avatar.png\"}\n shape=\"circle\"\n size={50}\n />\n\n <Image.Avatar shape=\"circle\" />\n <Image.Avatar gender=\"M\" shape=\"circle\" size={80} />\n <Image.Avatar gender=\"female\" shape=\"circle\" size={50} />\n <Image.Avatar gender=\"m\" shape=\"circle\" size={50} />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n}]\n},{\n title: `自定义状态组件`,\n description: `自定义加载中和错误状态的显示组件`,\n code: `const { default: Image } = _Image;\nconst { Space, Card, Spin, Alert } = antd;\nconst { default: Icon } = icon;\n\nconst CustomStatesExample = () => {\n const customLoading = (\n <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', width: '100px', height: '100px' }}>\n <Spin size=\"large\" />\n </div>\n );\n \n const customError = (\n <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', width: '100px', height: '100px', background: '#f5f5f5' }}>\n <Icon type=\"icon-exclamation-circle\" style={{ fontSize: 24, color: '#ff4d4f' }} />\n </div>\n );\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"自定义加载状态\" size=\"small\">\n <Space>\n <div>\n <div style={{ marginBottom: 8 }}>默认加载状态:</div>\n <Image src=\"https://picsum.photos/seed/loading1/100/100.jpg\" style={{ width: '100px', height: '100px' }} />\n </div>\n <div>\n <div style={{ marginBottom: 8 }}>自定义加载状态:</div>\n <Image \n src=\"https://picsum.photos/seed/loading2/100/100.jpg\" \n loading={customLoading}\n style={{ width: '100px', height: '100px' }} \n />\n </div>\n </Space>\n </Card>\n \n <Card title=\"自定义错误状态\" size=\"small\">\n <Space>\n <div>\n <div style={{ marginBottom: 8 }}>默认错误状态:</div>\n <Image src=\"https://invalid-url.example.com/image.jpg\" style={{ width: '100px', height: '100px' }} />\n </div>\n <div>\n <div style={{ marginBottom: 8 }}>自定义错误状态:</div>\n <Image \n src=\"https://invalid-url2.example.com/image.jpg\" \n error={customError}\n style={{ width: '100px', height: '100px' }} \n />\n </div>\n </Space>\n </Card>\n \n <Card title=\"说明\" size=\"small\">\n <Alert \n message=\"自定义状态组件\" \n description=\"Image 组件支持自定义加载中和错误状态的显示组件,可以通过 loading 和 error 属性传入自定义的 ReactNode。\"\n type=\"info\" \n />\n </Card>\n </Space>\n );\n};\n\nrender(<CustomStatesExample />);\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n},{\n name: \"icon\",\n packageName: \"@components/Icon\",\n component: component_49\n}]\n},{\n title: `图片交互`,\n description: `展示图片点击事件和图片预览功能`,\n code: `const { default: Image } = _Image;\nconst { Space, Card, Modal, Typography, Button } = antd;\nconst { useState } = React;\n\nconst { Text } = Typography;\n\nconst ImageInteractionExample = () => {\n const [previewVisible, setPreviewVisible] = useState(false);\n const [previewImage, setPreviewImage] = useState('');\n\n const handleImageClick = (src) => {\n setPreviewImage(src);\n setPreviewVisible(true);\n };\n\n const handlePreviewClose = () => {\n setPreviewVisible(false);\n };\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"图片点击事件\" size=\"small\">\n <Space direction=\"vertical\">\n <Text type=\"secondary\">点击图片查看大图:</Text>\n <Space wrap>\n <Image\n src=\"https://picsum.photos/seed/product1/150/150.jpg\"\n style={{ \n width: '150px', \n height: '150px', \n cursor: 'pointer',\n border: '1px solid #d9d9d9',\n borderRadius: '4px'\n }}\n onClick={() => handleImageClick('https://picsum.photos/seed/product1/600/600.jpg')}\n alt=\"产品图片1\"\n />\n <Image\n src=\"https://picsum.photos/seed/product2/150/150.jpg\"\n style={{ \n width: '150px', \n height: '150px', \n cursor: 'pointer',\n border: '1px solid #d9d9d9',\n borderRadius: '4px'\n }}\n onClick={() => handleImageClick('https://picsum.photos/seed/product2/600/600.jpg')}\n alt=\"产品图片2\"\n />\n <Image\n src=\"https://picsum.photos/seed/product3/150/150.jpg\"\n style={{ \n width: '150px', \n height: '150px', \n cursor: 'pointer',\n border: '1px solid #d9d9d9',\n borderRadius: '4px'\n }}\n onClick={() => handleImageClick('https://picsum.photos/seed/product3/600/600.jpg')}\n alt=\"产品图片3\"\n />\n </Space>\n </Space>\n </Card>\n \n <Card title=\"可点击头像\" size=\"small\">\n <Space>\n <div style={{ textAlign: 'center' }}>\n <Image.Avatar\n src=\"https://picsum.photos/seed/user1/100/100.jpg\"\n size={80}\n shape=\"circle\"\n onClick={() => console.log('点击了用户头像')}\n style={{ cursor: 'pointer' }}\n alt=\"用户头像\"\n />\n <div style={{ marginTop: 8, fontSize: 12 }}>用户头像</div>\n </div>\n <div style={{ textAlign: 'center' }}>\n <Image.Avatar\n gender=\"female\"\n size={80}\n shape=\"circle\"\n onClick={() => console.log('点击了默认女性头像')}\n style={{ cursor: 'pointer' }}\n />\n <div style={{ marginTop: 8, fontSize: 12 }}>默认女性头像</div>\n </div>\n </Space>\n </Card>\n \n <Card title=\"说明\" size=\"small\">\n <Text>\n <div>1. Image 和 Image.Avatar 组件都支持 onClick 事件,可以添加交互功能。</div>\n <div>2. 结合 Modal 组件可以实现图片预览功能。</div>\n <div>3. 通过设置 cursor: 'pointer' 样式可以提示用户图片是可点击的。</div>\n </Text>\n </Card>\n \n <Modal\n open={previewVisible}\n title=\"图片预览\"\n footer={[\n <Button key=\"close\" onClick={handlePreviewClose}>\n 关闭\n </Button>\n ]}\n width={700}\n onCancel={handlePreviewClose}\n >\n <div style={{ textAlign: 'center' }}>\n <img src={previewImage} alt=\"预览\" style={{ maxWidth: '100%' }} />\n </div>\n </Modal>\n </Space>\n );\n};\n\nrender(<ImageInteractionExample />);\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n}]\n},{\n title: `真实业务场景`,\n description: `用户信息卡片中的头像和商品列表中的图片展示`,\n code: `const { default: Image } = _Image;\nconst { Space, Card, Typography, List, Avatar, Tag } = antd;\n\nconst { Title, Text, Paragraph } = Typography;\n\nconst RealScenarioExample = () => {\n // 模拟用户数据\n const users = [\n {\n id: 1,\n name: '张三',\n avatar: 'https://api.dicebear.com/7.x/avataaars/svg?seed=zhangsan',\n position: '前端开发工程师',\n department: '技术部'\n },\n {\n id: 2,\n name: '李四',\n avatar: '',\n gender: 'male',\n position: '产品经理',\n department: '产品部'\n },\n {\n id: 3,\n name: '王五',\n avatar: '',\n gender: 'female',\n position: 'UI设计师',\n department: '设计部'\n }\n ];\n\n // 模拟商品数据\n const products = [\n {\n id: 1,\n name: '高端笔记本电脑',\n image: 'https://picsum.photos/seed/laptop/200/200.jpg',\n price: 8999,\n status: '在售'\n },\n {\n id: 2,\n name: '无线蓝牙耳机',\n image: 'https://picsum.photos/seed/earphone/200/200.jpg',\n price: 499,\n status: '在售'\n },\n {\n id: 3,\n name: '智能手表',\n image: 'https://picsum.photos/seed/watch/200/200.jpg',\n price: 1299,\n status: '缺货'\n }\n ];\n\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"用户信息卡片\" size=\"small\">\n <List\n dataSource={users}\n renderItem={(user) => (\n <List.Item style={{ padding: '12px 0', borderBottom: '1px solid #f0f0f0' }}>\n <List.Item.Meta\n avatar={\n user.avatar ? (\n <Image.Avatar\n src={user.avatar}\n size={50}\n shape=\"circle\"\n alt={user.name}\n />\n ) : (\n <Image.Avatar\n gender={user.gender}\n size={50}\n shape=\"circle\"\n />\n )\n }\n title={\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <Text strong>{user.name}</Text>\n <Tag color=\"blue\" style={{ marginLeft: 8 }}>\n {user.department}\n </Tag>\n </div>\n }\n description={user.position}\n />\n </List.Item>\n )}\n />\n </Card>\n \n <Card title=\"商品展示列表\" size=\"small\">\n <List\n grid={{ gutter: 16, column: 3 }}\n dataSource={products}\n renderItem={(product) => (\n <List.Item>\n <Card\n size=\"small\"\n hoverable\n cover={\n <Image\n src={product.image}\n style={{ \n width: '100%', \n height: 180, \n objectFit: 'cover' \n }}\n alt={product.name}\n />\n }\n >\n <Card.Meta\n title={product.name}\n description={\n <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>\n <Text strong style={{ color: '#f5222d' }}>\n ¥{product.price}\n </Text>\n <Tag color={product.status === '在售' ? 'green' : 'red'}>\n {product.status}\n </Tag>\n </div>\n }\n />\n </Card>\n </List.Item>\n )}\n />\n </Card>\n \n <Card title=\"说明\" size=\"small\">\n <Paragraph>\n 本示例展示了 Image 组件在真实业务场景中的应用:\n </Paragraph>\n <ul>\n <li>用户信息卡片中的头像展示,支持图片头像和默认性别图标头像</li>\n <li>商品展示列表中的图片展示,支持加载状态和错误处理</li>\n <li>结合其他组件(List、Card、Tag等)实现完整的功能页面</li>\n </ul>\n </Card>\n </Space>\n );\n};\n\nrender(<RealScenarioExample />);\n`,\n scope: [{\n name: \"_Image\",\n packageName: \"@components/Image\",\n component: component_46\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_47\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_71 from '@kne/info-page';\nimport '@kne/info-page/dist/index.css';\nimport * as component_73 from 'antd';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport * as component_82 from '@kne/remote-loader';\nimport * as component_83 from '@ant-design/icons';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nimport '@kne/info-page/dist/index.css';\nconst readmeConfig = {\n name: `info-page`,\n summary: `<p>info-page 是一个专为复杂详情展示页面设计的 React 组件库,提供标准化的信息展示格式和丰富的布局选项。</p>\n<h2>核心特性</h2>\n<ul>\n<li><strong>统一的信息展示标准</strong>:提供一致的详情页面展示格式,确保用户体验的连贯性</li>\n<li><strong>灵活的布局组件</strong>:包含多种布局方式,支持网格、表格、分栏等多种展示形式</li>\n<li><strong>强大的数据处理能力</strong>:内置数据格式化、空值处理、条件显示等实用功能</li>\n<li><strong>高度可定制化</strong>:支持自定义渲染、样式定制和扩展配置</li>\n<li><strong>现代化设计</strong>:基于 Ant Design 构建,支持响应式布局</li>\n</ul>\n<h2>适用场景</h2>\n<ul>\n<li><strong>管理系统详情页</strong>:用户信息、订单详情、产品信息等复杂展示场景</li>\n<li><strong>数据报告页面</strong>:需要结构化展示多维度数据的报表和统计页面</li>\n<li><strong>工作流展示</strong>:流程审批记录、操作历史等时序信息展示</li>\n<li><strong>数据对比页面</strong>:多列对比展示、评分系统等</li>\n<li><strong>打印友好设计</strong>:支持分页打印的报告生成</li>\n</ul>\n<h2>技术亮点</h2>\n<ul>\n<li><strong>组件化设计</strong>:提供 InfoPage、Content、TableView、Flow 等独立组件,可单独使用也可组合使用</li>\n<li><strong>智能列计算</strong>:自动计算列宽、响应式布局适配,支持固定列和自适应列混合使用</li>\n<li><strong>丰富的格式化选项</strong>:内置日期、数字、货币、布尔值等多种数据格式化器</li>\n<li><strong>条件渲染机制</strong>:支持基于数据动态控制字段显示状态</li>\n<li><strong>TypeScript 友好</strong>:完整的类型定义支持,提供良好的开发体验</li>\n</ul>`,\n \n \n api: `<h3>InfoPage</h3>\n<p>信息展示页面容器组件,提供统一的页面布局和间距控制</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>子组件内容</td>\n</tr>\n</tbody>\n</table>\n<h3>InfoPage.Part</h3>\n<p>信息展示区块组件,用于包装具体的信息内容</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n<tr>\n<td>title</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>区块标题</td>\n</tr>\n<tr>\n<td>subtitle</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>区块副标题</td>\n</tr>\n<tr>\n<td>extra</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>区块额外操作区域</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>区块内容</td>\n</tr>\n<tr>\n<td>bordered</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否显示额外边框样式</td>\n</tr>\n</tbody>\n</table>\n<h3>Content / InfoList</h3>\n<p>通用内容展示组件,支持标签-内容的灵活布局</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>list</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>展示数据列表</td>\n</tr>\n<tr>\n<td>labelAlign</td>\n<td>string</td>\n<td>否</td>\n<td>'left'</td>\n<td>标签对齐方式,可选 'left'、'center'、'right'、'auto'</td>\n</tr>\n<tr>\n<td>col</td>\n<td>number</td>\n<td>否</td>\n<td>1</td>\n<td>每行显示的列数</td>\n</tr>\n<tr>\n<td>gutter</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n<td>栅格间隔</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n<tr>\n<td>size</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>尺寸大小,可选 'small'</td>\n</tr>\n<tr>\n<td>itemRender</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>自定义列表项渲染函数</td>\n</tr>\n</tbody>\n</table>\n<h4>列表项数据结构</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>label</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>标签内容</td>\n</tr>\n<tr>\n<td>content</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>内容区域</td>\n</tr>\n<tr>\n<td>block</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否占据整行</td>\n</tr>\n<tr>\n<td>display</td>\n<td>boolean/function</td>\n<td>否</td>\n<td>true</td>\n<td>是否显示该项</td>\n</tr>\n</tbody>\n</table>\n<h3>Descriptions / DetailList</h3>\n<p>描述列表组件,类似于 Ant Design 的 Descriptions,专为详情页设计</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>二维数组数据源,每个子数组代表一行</td>\n</tr>\n<tr>\n<td>isFull</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>标签是否占据更大空间</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n<tr>\n<td>itemRender</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>自定义项渲染函数</td>\n</tr>\n</tbody>\n</table>\n<h3>CentralContent / FieldView</h3>\n<p>居中内容展示组件,支持列定义和自动布局</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>object</td>\n<td>否</td>\n<td>{}</td>\n<td>数据源对象</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>列定义数组</td>\n</tr>\n<tr>\n<td>col</td>\n<td>number</td>\n<td>否</td>\n<td>2</td>\n<td>展示列数</td>\n</tr>\n<tr>\n<td>type</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>组件类型,可选 'compact'(紧凑模式)</td>\n</tr>\n<tr>\n<td>valueIsEmpty</td>\n<td>function</td>\n<td>否</td>\n<td>isEmpty</td>\n<td>值为空的判断函数</td>\n</tr>\n<tr>\n<td>emptyIsPlaceholder</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n<td>空值是否显示占位符</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>'-'</td>\n<td>空值占位符</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n<tr>\n<td>context</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>上下文数据</td>\n</tr>\n</tbody>\n</table>\n<h4>列定义数据结构</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>字段名称</td>\n</tr>\n<tr>\n<td>title</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>显示标题</td>\n</tr>\n<tr>\n<td>format</td>\n<td>string/function</td>\n<td>否</td>\n<td>-</td>\n<td>格式化规则</td>\n</tr>\n<tr>\n<td>render</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>自定义渲染函数</td>\n</tr>\n<tr>\n<td>span</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n<td>栅格占位格数</td>\n</tr>\n<tr>\n<td>block</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否占据整行</td>\n</tr>\n</tbody>\n</table>\n<h3>TableView</h3>\n<p>表格视图组件,支持行选择和自定义列配置</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>表格数据源</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>列定义数组</td>\n</tr>\n<tr>\n<td>rowKey</td>\n<td>string/function</td>\n<td>否</td>\n<td>'id'</td>\n<td>行数据的唯一标识</td>\n</tr>\n<tr>\n<td>rowSelection</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>行选择配置</td>\n</tr>\n<tr>\n<td>valueIsEmpty</td>\n<td>function</td>\n<td>否</td>\n<td>isEmpty</td>\n<td>值为空的判断函数</td>\n</tr>\n<tr>\n<td>emptyIsPlaceholder</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n<td>空值是否显示占位符</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>'-'</td>\n<td>空值占位符</td>\n</tr>\n<tr>\n<td>empty</td>\n<td>ReactNode</td>\n<td>否</td>\n<td><Empty /></td>\n<td>空数据展示内容</td>\n</tr>\n<tr>\n<td>onRowSelect</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>行选择回调函数</td>\n</tr>\n<tr>\n<td>render</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>自定义渲染函数</td>\n</tr>\n<tr>\n<td>context</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>上下文数据</td>\n</tr>\n<tr>\n<td>sticky</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>表头是否固定</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n</tbody>\n</table>\n<h4>行选择配置</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>type</td>\n<td>string</td>\n<td>否</td>\n<td>'checkbox'</td>\n<td>选择类型,可选 'checkbox'、'radio'</td>\n</tr>\n<tr>\n<td>selectedRowKeys</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>已选中行的key数组</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>function</td>\n<td>否</td>\n<td>-</td>\n<td>选择变化回调函数</td>\n</tr>\n<tr>\n<td>isSelectedAll</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否全选状态</td>\n</tr>\n<tr>\n<td>allowSelectedAll</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否允许全选(配合 isSelectedAll 使用)</td>\n</tr>\n</tbody>\n</table>\n<h3>Flow</h3>\n<p>流程展示组件,基于 Ant Design Steps 组件扩展</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>流程数据源</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>array</td>\n<td>否</td>\n<td>[]</td>\n<td>列定义数组</td>\n</tr>\n<tr>\n<td>size</td>\n<td>string</td>\n<td>否</td>\n<td>'small'</td>\n<td>步骤条大小</td>\n</tr>\n<tr>\n<td>current</td>\n<td>number</td>\n<td>否</td>\n<td>-</td>\n<td>当前步骤(从0开始)</td>\n</tr>\n<tr>\n<td>direction</td>\n<td>string</td>\n<td>否</td>\n<td>'vertical'</td>\n<td>步骤条方向,可选 'vertical'、'horizontal'</td>\n</tr>\n<tr>\n<td>progressDot</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否使用点状步骤条</td>\n</tr>\n<tr>\n<td>labelPlacement</td>\n<td>string</td>\n<td>否</td>\n<td>'vertical'</td>\n<td>标签位置,可选 'vertical'、'horizontal'</td>\n</tr>\n<tr>\n<td>empty</td>\n<td>ReactNode</td>\n<td>否</td>\n<td><Empty /></td>\n<td>空数据展示内容</td>\n</tr>\n<tr>\n<td>valueIsEmpty</td>\n<td>function</td>\n<td>否</td>\n<td>isEmpty</td>\n<td>值为空的判断函数</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>'-'</td>\n<td>空值占位符</td>\n</tr>\n<tr>\n<td>emptyIsPlaceholder</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>空值是否显示占位符</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n</tbody>\n</table>\n<h4>columns 列定义支持的 type 类型</h4>\n<table>\n<thead>\n<tr>\n<th>type</th>\n<th>说明</th>\n<th>特殊处理</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>标题</td>\n<td>-</td>\n</tr>\n<tr>\n<td>subTitle</td>\n<td>副标题</td>\n<td>-</td>\n</tr>\n<tr>\n<td>description</td>\n<td>描述</td>\n<td>-</td>\n</tr>\n<tr>\n<td>status</td>\n<td>状态</td>\n<td>-</td>\n</tr>\n<tr>\n<td>content</td>\n<td>额外内容</td>\n<td>渲染为独立区块</td>\n</tr>\n<tr>\n<td>actionList</td>\n<td>操作列表</td>\n<td>唯一支持 children 的类型</td>\n</tr>\n</tbody>\n</table>\n<h3>SplitLine</h3>\n<p>分割线展示组件,用于横向展示多个字段</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>dataSource</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>数据源对象</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>列定义数组</td>\n</tr>\n<tr>\n<td>valueIsEmpty</td>\n<td>function</td>\n<td>否</td>\n<td>isEmpty</td>\n<td>值为空的判断函数</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>'-'</td>\n<td>空值占位符</td>\n</tr>\n<tr>\n<td>emptyIsPlaceholder</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>空值是否显示占位符</td>\n</tr>\n<tr>\n<td>size</td>\n<td>number</td>\n<td>否</td>\n<td>0</td>\n<td>分割线间距</td>\n</tr>\n<tr>\n<td>labelGap</td>\n<td>number</td>\n<td>否</td>\n<td>4</td>\n<td>标签与内容的间距</td>\n</tr>\n<tr>\n<td>labelMode</td>\n<td>string</td>\n<td>否</td>\n<td>'horizontal'</td>\n<td>标签模式,可选 'horizontal'、'vertical'</td>\n</tr>\n<tr>\n<td>split</td>\n<td>ReactNode</td>\n<td>否</td>\n<td><Divider type=\"vertical\" /></td>\n<td>分割线组件</td>\n</tr>\n<tr>\n<td>context</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>上下文数据</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n</tbody>\n</table>\n<h4>columns 列定义特殊属性</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>icon</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>图标元素</td>\n</tr>\n</tbody>\n</table>\n<h3>Report</h3>\n<p>报告容器组件,用于生成打印友好的报告页面</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>报告标题</td>\n</tr>\n<tr>\n<td>subtitle</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>报告副标题</td>\n</tr>\n<tr>\n<td>extra</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>标题额外内容</td>\n</tr>\n<tr>\n<td>border</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n<td>是否显示边框</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>子组件内容</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n</tbody>\n</table>\n<h3>Report.List</h3>\n<p>报告列表子组件,展示键值对形式的报告内容</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>report</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n<td>报告数据对象,包含 list 数组</td>\n</tr>\n<tr>\n<td>report.list</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>列表项数组,每项包含 label、content 等</td>\n</tr>\n</tbody>\n</table>\n<h3>Report.Result</h3>\n<p>报告结果子组件,展示评分结果和详细描述</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>report</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n<td>报告数据对象,包含 total 和 list</td>\n</tr>\n<tr>\n<td>report.total</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n<td>总分信息,包含 score、label</td>\n</tr>\n<tr>\n<td>report.list</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>评分明细列表,每项包含 label、score、content</td>\n</tr>\n</tbody>\n</table>\n<h3>Report.Table</h3>\n<p>报告表格子组件,展示分组评分表格</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>report</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n<td>报告数据对象</td>\n</tr>\n<tr>\n<td>report.columns</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>表格列定义</td>\n</tr>\n<tr>\n<td>report.group</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>分组定义数组,每项包含 name、label</td>\n</tr>\n<tr>\n<td>report.list</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>表格数据列表</td>\n</tr>\n</tbody>\n</table>\n<h3>Report.Part</h3>\n<p>报告内容区块子组件,展示段落形式的内容</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>report</td>\n<td>object</td>\n<td>是</td>\n<td>-</td>\n<td>报告数据对象,包含 list 数组</td>\n</tr>\n<tr>\n<td>report.list</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>内容项数组,每项包含 label、content 等</td>\n</tr>\n</tbody>\n</table>\n<h3>Report.Score</h3>\n<p>报告评分展示子组件</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>number</td>\n<td>是</td>\n<td>-</td>\n<td>当前评分值</td>\n</tr>\n</tbody>\n</table>\n<h3>Score</h3>\n<p>评分展示组件,以星形图标展示评分</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>value</td>\n<td>number</td>\n<td>是</td>\n<td>-</td>\n<td>当前评分值</td>\n</tr>\n<tr>\n<td>gap</td>\n<td>number</td>\n<td>否</td>\n<td>4</td>\n<td>评分项之间的间距</td>\n</tr>\n<tr>\n<td>total</td>\n<td>number</td>\n<td>否</td>\n<td>5</td>\n<td>总评分项数</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义样式类名</td>\n</tr>\n</tbody>\n</table>\n<h3>formatView</h3>\n<p>数据格式化工具函数,提供多种常用格式化规则</p>\n<h4>方法说明</h4>\n<table>\n<thead>\n<tr>\n<th>方法名</th>\n<th>参数</th>\n<th>返回值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>default</td>\n<td>(value, format, context)</td>\n<td>string/object</td>\n<td>根据格式规则格式化数据</td>\n</tr>\n</tbody>\n</table>\n<h4>支持的格式化规则</h4>\n<table>\n<thead>\n<tr>\n<th>格式名</th>\n<th>说明</th>\n<th>参数</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>date</td>\n<td>日期格式化</td>\n<td>模板字符串,默认 'YYYY-MM-DD'</td>\n</tr>\n<tr>\n<td>datetime</td>\n<td>日期时间格式化</td>\n<td>模板字符串,默认 'YYYY-MM-DD HH:mm:ss'</td>\n</tr>\n<tr>\n<td>dateRange</td>\n<td>日期范围格式化</td>\n<td>模板字符串、是否允许空值</td>\n</tr>\n<tr>\n<td>boolean</td>\n<td>布尔值格式化</td>\n<td>true值对应的文本,默认 'true'</td>\n</tr>\n<tr>\n<td>number</td>\n<td>数字格式化</td>\n<td>样式、单位、小数位数等</td>\n</tr>\n<tr>\n<td>money</td>\n<td>金额格式化</td>\n<td>单位,默认 '元'</td>\n</tr>\n</tbody>\n</table>\n<h3>computeColumnsValue</h3>\n<p>列值计算工具函数,用于统一处理列数据的显示逻辑</p>\n<h4>方法说明</h4>\n<table>\n<thead>\n<tr>\n<th>方法名</th>\n<th>参数</th>\n<th>返回值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>default</td>\n<td>(config)</td>\n<td>array</td>\n<td>计算列的显示值</td>\n</tr>\n<tr>\n<td>computeDisplay</td>\n<td>(config)</td>\n<td>ReactNode</td>\n<td>计算单个列的显示内容</td>\n</tr>\n<tr>\n<td>computeColumnsDisplay</td>\n<td>(config)</td>\n<td>array</td>\n<td>计算所有列的显示内容</td>\n</tr>\n</tbody>\n</table>\n<h4>配置参数</h4>\n<table>\n<thead>\n<tr>\n<th>参数名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>columns</td>\n<td>array</td>\n<td>是</td>\n<td>-</td>\n<td>列定义数组</td>\n</tr>\n<tr>\n<td>dataSource</td>\n<td>object/array</td>\n<td>是</td>\n<td>-</td>\n<td>数据源</td>\n</tr>\n<tr>\n<td>context</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>上下文数据</td>\n</tr>\n<tr>\n<td>valueIsEmpty</td>\n<td>function</td>\n<td>否</td>\n<td>isEmpty</td>\n<td>值为空的判断函数</td>\n</tr>\n<tr>\n<td>emptyIsPlaceholder</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n<td>空值是否显示占位符</td>\n</tr>\n<tr>\n<td>removeEmpty</td>\n<td>boolean</td>\n<td>否</td>\n<td>true</td>\n<td>是否移除空值列</td>\n</tr>\n<tr>\n<td>placeholder</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>'-'</td>\n<td>空值占位符</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础布局`,\n description: `展示InfoPage容器组件和Part区块组件的基本使用方法`,\n code: `const { default: InfoPage } = _InfoPage;\nconst { Button, Space, Flex, Tag } = antd;\n\nconst BaseExample = () => {\n return (\n <Flex vertical gap={24}>\n <Space direction=\"vertical\" size={16}>\n {/* 基础 Part 使用 */}\n <InfoPage.Part title=\"个人信息\" subtitle=\"展示基础 Part 用法\">\n <Space direction=\"vertical\" size={8}>\n <div><strong>姓名:</strong>张三</div>\n <div><strong>性别:</strong>男</div>\n <div><strong>年龄:</strong>28岁</div>\n </Space>\n </InfoPage.Part>\n\n {/* 带 extra 的 Part */}\n <InfoPage.Part \n title=\"联系方式\" \n subtitle=\"展示标题和额外操作区\"\n extra={<Button type=\"primary\" size=\"small\">编辑</Button>}\n >\n <Space direction=\"vertical\" size={8}>\n <div><strong>手机:</strong>138-0013-8000</div>\n <div><strong>邮箱:</strong>zhangsan@example.com</div>\n <div><strong>地址:</strong>深圳市南山区科技园</div>\n </Space>\n </InfoPage.Part>\n\n {/* 嵌套 Part */}\n <InfoPage.Part title=\"工作经历\">\n <p>以下展示了 Part 的嵌套使用:</p>\n <InfoPage.Part subtitle=\"现任职位\" style={{ background: '#f5f5f5', padding: '12px' }}>\n <Space direction=\"vertical\" size={8}>\n <div><strong>公司:</strong>腾讯科技</div>\n <div><strong>职位:</strong>高级前端工程师</div>\n <div><strong>入职时间:</strong>2020年3月</div>\n </Space>\n </InfoPage.Part>\n </InfoPage.Part>\n\n {/* 带 bordered 的 Part */}\n <InfoPage.Part title=\"项目经验\" bordered>\n <Space direction=\"vertical\" size={8}>\n <div><strong>项目名称:</strong>企业级管理系统</div>\n <div><strong>技术栈:</strong>React、TypeScript、Ant Design</div>\n <div><strong>职责:</strong>负责前端架构设计与核心功能开发</div>\n </Space>\n </InfoPage.Part>\n\n {/* Collapse 折叠面板 */}\n <InfoPage.Collapse\n items={[\n { \n key: '1', \n label: '教育背景', \n children: (\n <Space direction=\"vertical\" size={8}>\n <div><strong>学校:</strong>深圳大学</div>\n <div><strong>专业:</strong>计算机科学与技术</div>\n <div><strong>学历:</strong>本科</div>\n <div><strong>毕业时间:</strong>2018年6月</div>\n </Space>\n )\n },\n { \n key: '2', \n label: '技能证书', \n children: (\n <Space wrap>\n <Tag color=\"blue\">PMP项目管理</Tag>\n <Tag color=\"green\">阿里云ACP认证</Tag>\n <Tag color=\"purple\">AWS解决方案架构师</Tag>\n </Space>\n )\n }\n ]}\n />\n\n {/* 无标题 Part */}\n <InfoPage.Part>\n <div style={{ color: '#666', padding: '12px', background: '#fafafa' }}>\n <strong>备注:</strong>以上信息仅供示例展示,不代表真实数据\n </div>\n </InfoPage.Part>\n </Space>\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `内容列表`,\n description: `支持多列布局和标签对齐的灵活内容展示组件`,\n code: `const { Content } = _InfoPage;\nconst { Space, Radio, Tag } = antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [listProps, setListProps] = useState({\n col: 2,\n size: 'default',\n labelAlign: 'left'\n });\n\n const onChange = (e, name) => {\n const val = e?.target.value;\n setListProps(prevState => Object.assign({}, prevState, { [name]: val }));\n };\n\n return (\n <Space direction='vertical' size={16}>\n {/* 控制面板 */}\n <div style={{ background: '#f5f5f5', padding: '16px', borderRadius: '8px' }}>\n <Space direction=\"vertical\" size={12} style={{ width: '100%' }}>\n <div>\n <span style={{ marginRight: 8 }}>列数:</span>\n <Radio.Group onChange={(e) => onChange(e, 'col')} value={listProps.col}>\n <Radio.Button value={1}>单列</Radio.Button>\n <Radio.Button value={2}>两列</Radio.Button>\n <Radio.Button value={3}>三列</Radio.Button>\n </Radio.Group>\n </div>\n <div>\n <span style={{ marginRight: 8 }}>标签对齐:</span>\n <Radio.Group onChange={(e) => onChange(e, 'labelAlign')} value={listProps.labelAlign}>\n <Radio.Button value='left'>左对齐</Radio.Button>\n <Radio.Button value='center'>居中</Radio.Button>\n <Radio.Button value='right'>右对齐</Radio.Button>\n <Radio.Button value='auto'>自适应</Radio.Button>\n </Radio.Group>\n </div>\n <div>\n <span style={{ marginRight: 8 }}>尺寸:</span>\n <Radio.Group onChange={(e) => onChange(e, 'size')} value={listProps.size}>\n <Radio.Button value='default'>默认</Radio.Button>\n <Radio.Button value='small'>小尺寸</Radio.Button>\n </Radio.Group>\n </div>\n </Space>\n </div>\n\n {/* Content 组件展示 */}\n <Content\n {...listProps}\n list={[\n { label: '客户名称', content: '深圳市腾讯计算机系统有限公司' },\n { label: '统一社会信用代码', content: '914403007109410773' },\n { label: '法定代表人', content: '马化腾' },\n { label: '企业类型', content: <Tag color=\"blue\">有限责任公司</Tag> },\n { label: '成立日期', content: '1998-11-11' },\n { label: '注册资本', content: '500万美元' },\n { label: '经营状态', content: <Tag color=\"success\">存续</Tag> },\n { label: '注册地址', content: '深圳市南山区高新科技园科技中一路腾讯大厦' },\n {\n label: '经营范围',\n content: '计算机软硬件的技术开发、销售;计算机网络工程;系统集成;软件开发及技术服务;信息咨询;网络设备、通讯设备、电子产品的技术开发与销售;国内贸易。',\n block: true\n }\n ]}\n itemRender={(inner, other) => {\n return other?.index === 8 ? <div style={{ color: '#999', fontSize: '12px', marginTop: '8px' }}>\n * 以上信息仅供展示,不代表真实数据\n </div> : inner;\n }}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `内容展示`,\n description: `展示Content组件的各种配置和用法`,\n code: `const { Content } = _InfoPage;\nconst { Flex, Radio, Space, Tag, Avatar } = antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [listProps, setListProps] = useState({\n col: 2,\n size: 'default',\n labelAlign: 'auto',\n gutter: 16\n });\n\n const [showDisabled, setShowDisabled] = useState(false);\n\n const onChange = (e, name) => {\n const val = e?.target.value;\n setListProps(prevState => ({ ...prevState, [name]: val }));\n };\n\n const dataList = [\n { label: '客户姓名', content: <Flex align=\"center\" gap={8}><Avatar size=\"small\">张</Avatar>张三</Flex>, block: true },\n { label: '客户编号', content: 'C20240115001' },\n { label: '联系电话', content: '138-0013-8000' },\n { label: '电子邮箱', content: 'zhangsan@example.com' },\n { label: '客户类型', content: <Tag color=\"blue\">VIP客户</Tag> },\n { label: '信用等级', content: <Tag color=\"green\">A级</Tag> },\n { label: '所属公司', content: '深圳市腾讯计算机系统有限公司', block: true },\n { label: '所在部门', content: '技术部', display: !showDisabled },\n { label: '职位', content: '高级前端工程师', display: !showDisabled },\n { label: '注册时间', content: '2020-03-15' },\n { label: '最后登录', content: '2024-01-15 10:30:00' },\n { label: '账户状态', content: <Tag color=\"success\">正常</Tag> },\n { label: '备注信息', content: '该客户为公司长期合作伙伴,合作期间表现优秀,建议继续保持良好合作关系。', block: true }\n ];\n\n return (\n <Flex vertical gap={16}>\n {/* 控制面板 */}\n <Space direction=\"vertical\" size={12} style={{ background: '#f5f5f5', padding: '16px', borderRadius: '8px' }}>\n <div>\n <span style={{ marginRight: 8 }}>列数:</span>\n <Radio.Group onChange={(e) => onChange(e, 'col')} value={listProps.col}>\n <Radio.Button value={1}>单列</Radio.Button>\n <Radio.Button value={2}>两列</Radio.Button>\n <Radio.Button value={3}>三列</Radio.Button>\n <Radio.Button value={4}>四列</Radio.Button>\n </Radio.Group>\n </div>\n\n <div>\n <span style={{ marginRight: 8 }}>标签对齐:</span>\n <Radio.Group onChange={(e) => onChange(e, 'labelAlign')} value={listProps.labelAlign}>\n <Radio.Button value='left'>左对齐</Radio.Button>\n <Radio.Button value='center'>居中</Radio.Button>\n <Radio.Button value='right'>右对齐</Radio.Button>\n <Radio.Button value='auto'>自适应</Radio.Button>\n </Radio.Group>\n </div>\n\n <div>\n <span style={{ marginRight: 8 }}>尺寸:</span>\n <Radio.Group onChange={(e) => onChange(e, 'size')} value={listProps.size}>\n <Radio.Button value='default'>默认</Radio.Button>\n <Radio.Button value='small'>小尺寸</Radio.Button>\n </Radio.Group>\n </div>\n\n <div>\n <span style={{ marginRight: 8 }}>显示隐藏:</span>\n <Radio.Group onChange={(e) => setShowDisabled(e.target.value)} value={showDisabled}>\n <Radio.Button value={false}>显示全部</Radio.Button>\n <Radio.Button value={true}>隐藏部分</Radio.Button>\n </Radio.Group>\n </div>\n </Space>\n\n {/* Content 组件展示 */}\n <Content\n {...listProps}\n list={dataList.map(item => ({\n ...item,\n display: typeof item.display === 'boolean' ? item.display : undefined\n }))}\n />\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `描述列表`,\n description: `二维数组结构的详情信息展示,适合表单数据展示`,\n code: `const { Descriptions } = _InfoPage;\nconst { Tag, Space } = antd;\n\nconst BaseExample = () => {\n return (\n <Descriptions\n dataSource={[\n // 基本信息分组\n [\n { label: \"订单编号\", content: <strong style={{ color: '#1890ff' }}>ORD20240115001</strong> },\n { label: \"订单类型\", content: <Tag color=\"blue\">普通订单</Tag> },\n ],\n [\n { label: \"下单时间\", content: \"2024-01-15 10:30:25\" },\n { label: \"支付时间\", content: \"2024-01-15 10:32:18\" },\n ],\n [\n { label: \"客户名称\", content: \"深圳市腾讯计算机系统有限公司\" },\n { label: \"客户类型\", content: <Tag color=\"gold\">VIP客户</Tag> },\n ],\n // 收货信息分组\n [\n { label: \"收货人\", content: \"张三\" },\n { label: \"联系电话\", content: \"138-0013-8000\" },\n ],\n [\n { label: \"收货地址\", content: \"广东省深圳市南山区科技园科技中一路腾讯大厦A座18层\" },\n ],\n // 商品信息分组\n [\n {\n label: \"商品清单\",\n content: (\n <Space direction=\"vertical\" size={4}>\n <div>1. 腾讯云服务器(2核4G)× 1台 - ¥3000.00</div>\n <div>2. 云数据库 MySQL(50GB)× 1个 - ¥1200.00</div>\n <div>3. 对象存储(500GB)× 1个 - ¥800.00</div>\n </Space>\n ),\n },\n ],\n // 金额信息分组\n [\n { label: \"商品总额\", content: <strong>¥5,000.00</strong> },\n { label: \"运费\", content: \"¥0.00\" },\n ],\n [\n { label: \"优惠金额\", content: <span style={{ color: '#52c41a' }}>-¥750.00</span> },\n { label: \"实付金额\", content: <strong style={{ color: '#f5222d', fontSize: '16px' }}>¥4,250.00</strong> },\n ],\n // 发票信息分组\n [\n { label: \"发票类型\", content: \"增值税专用发票\" },\n { label: \"发票抬头\", content: \"深圳市腾讯计算机系统有限公司\" },\n ],\n [\n { label: \"纳税人识别号\", content: \"914403007109410773\" },\n { label: \"发票状态\", content: <Tag color=\"success\">已开具</Tag> },\n ],\n // 售后信息分组\n [\n { label: \"退款状态\", content: \"无退款\" },\n { label: \"发票抬头\", content: \"未申请\" },\n ],\n [\n { label: \"订单状态\", content: <Tag color=\"processing\">处理中</Tag> },\n {\n label: \"预计送达\",\n content: \"2024-01-17\",\n },\n ],\n // 备注信息\n [\n {\n label: \"订单备注\",\n content: \"请务必在工作日配送,配送前请提前电话联系收货人。收到商品后请当面验货,确认无误后再签收。\",\n block: true\n },\n ],\n // 操作记录\n [\n { label: \"创建时间\", content: \"2024-01-15 10:30:25\" },\n { label: \"创建人\", content: \"张三(客户)\" },\n ],\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `智能布局`,\n description: `支持数据格式化和自动栅格优化的高级内容展示组件`,\n code: `const { CentralContent } = _InfoPage;\nconst { Tag, Space } = antd;\n\nconst BaseExample = () => {\n return (\n <CentralContent\n dataSource={{\n id: 'RC20240115001',\n name: '张三',\n department: '技术研发部',\n position: '高级前端工程师',\n email: 'zhangsan@tencent.com',\n phone: '138-0013-8000',\n entryDate: '2020-03-15',\n workYears: 4,\n performanceScore: 92.5,\n salary: 35000,\n bonus: 50000,\n leaveDays: 5,\n projectCount: 8,\n description: \\`负责公司核心产品的前端架构设计与开发工作,主导了多个重要项目的技术方案设计。精通React、Vue等主流前端框架,对TypeScript有深入理解。在性能优化方面有丰富经验,成功将项目加载时间减少40%。\\`,\n skills: \\`React, Vue, TypeScript, Node.js, Webpack, Vite, Jenkins, Docker, Kubernetes\\`\n }}\n col={3}\n columns={[\n { name: 'id', title: '员工编号', block: true },\n { name: 'name', title: '姓名', span: 8 },\n { name: 'department', title: '部门' },\n { name: 'position', title: '职位', span: 10 },\n { name: 'email', title: '电子邮箱' },\n { name: 'phone', title: '联系电话' },\n { name: 'entryDate', title: '入职日期', format: 'date' },\n { name: 'workYears', title: '工作年限', format: 'number-suffix:年' },\n { name: 'performanceScore', title: '绩效评分', format: 'number-maximumFractionDigits:1-suffix:分' },\n { name: 'salary', title: '月薪', format: 'number-useGrouping:true-suffix:元' },\n { name: 'bonus', title: '年终奖金', format: 'number-useGrouping:true-suffix:元' },\n { name: 'leaveDays', title: '年度剩余年假', format: 'number-suffix:天' },\n { name: 'projectCount', title: '参与项目数', format: 'number-suffix:个' },\n { name: 'empty', title: '公积金账号' },\n { name: 'empty2', title: '社保卡号', placeholder: '未办理' },\n { name: 'description', title: '工作描述', block: true },\n { name: 'skills', title: '技能标签', render: (value) => (\n <Space wrap>\n {value.split(',').map(skill => (\n <Tag key={skill} color=\"blue\" style={{ marginBottom: 4 }}>{skill.trim()}</Tag>\n ))}\n </Space>\n )}\n ]}\n />\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `边框区块`,\n description: `展示InfoPage.Part的bordered属性配合CentralContent使用`,\n code: `const { default: InfoPage, CentralContent } = _InfoPage;\nconst { Tag, Avatar, Space, Modal, Button } = antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [open, setOpen] = useState(false);\n const baseInfo = (\n <InfoPage.Part bordered title=\"员工档案\" subtitle=\"基本信息\">\n <CentralContent\n type=\"compact\"\n dataSource={{\n id: 'RC20240115001',\n name: '张三',\n gender: '男',\n birthday: '1992-03-15',\n idCard: '440301199203154512',\n maritalStatus: '已婚',\n education: '本科',\n graduationSchool: '深圳大学',\n major: '计算机科学与技术',\n entryDate: '2020-03-15',\n workYears: 4,\n phone: '138-0013-8000',\n email: 'zhangsan@tencent.com',\n address: '广东省深圳市南山区科技园科技中一路腾讯大厦',\n emergencyContact: '李四',\n emergencyPhone: '139-0014-9000',\n emergencyRelation: '配偶'\n }}\n col={3}\n columns={[\n {\n name: 'id',\n title: '员工编号',\n block: true\n },\n {\n name: 'name',\n title: '姓名',\n render: value => (\n <Space align=\"center\">\n <Avatar style={{ backgroundColor: '#1890ff' }}>{value[0]}</Avatar>\n <strong>{value}</strong>\n </Space>\n ),\n span: 10\n },\n {\n name: 'gender',\n title: '性别'\n },\n {\n name: 'birthday',\n title: '出生日期',\n format: 'date'\n },\n {\n name: 'idCard',\n title: '身份证号',\n render: value => value.replace(/(\\d{6})(\\d{8})(\\d{4})/, '\\$1********\\$3')\n },\n {\n name: 'maritalStatus',\n title: '婚姻状况'\n },\n {\n name: 'education',\n title: '学历'\n },\n {\n name: 'graduationSchool',\n title: '毕业院校'\n },\n {\n name: 'major',\n title: '专业'\n },\n {\n name: 'entryDate',\n title: '入职日期',\n format: 'date'\n },\n {\n name: 'workYears',\n title: '工作年限',\n format: 'number-suffix:年'\n },\n {\n name: 'phone',\n title: '联系电话',\n render: value => value.replace(/(\\d{3})(\\d{4})(\\d{4})/, '\\$1-\\$2-\\$3')\n },\n {\n name: 'email',\n title: '电子邮箱'\n },\n {\n name: 'address',\n title: '家庭住址',\n block: true\n },\n {\n name: 'emergencyContact',\n title: '紧急联系人'\n },\n {\n name: 'emergencyPhone',\n title: '紧急联系电话',\n render: value => value.replace(/(\\d{3})(\\d{4})(\\d{4})/, '\\$1-\\$2-\\$3')\n },\n {\n name: 'emergencyRelation',\n title: '与本人关系'\n }\n ]}\n />\n </InfoPage.Part>\n );\n return (\n <InfoPage>\n {baseInfo}\n <InfoPage.Part bordered title=\"工作信息\" subtitle=\"部门与职位\">\n <CentralContent\n type=\"compact\"\n dataSource={{\n department: '技术研发部',\n position: '高级前端工程师',\n level: 'T4-2',\n supervisor: '王总监',\n team: '前端开发组',\n workLocation: '深圳总部',\n office: '腾讯大厦A座18层',\n workStatus: '在职',\n contractType: '正式员工',\n contractStartDate: '2023-03-15',\n contractEndDate: '2026-03-14',\n probationPeriod: '已转正'\n }}\n col={2}\n columns={[\n { name: 'department', title: '所属部门', span: 12 },\n { name: 'position', title: '职位', span: 12 },\n { name: 'level', title: '职级' },\n { name: 'supervisor', title: '直属主管' },\n { name: 'team', title: '所属团队' },\n { name: 'workLocation', title: '工作地点' },\n { name: 'office', title: '办公室位置' },\n { name: 'workStatus', title: '工作状态', render: value => <Tag color=\"success\">{value}</Tag> },\n { name: 'contractType', title: '合同类型' },\n { name: 'contractStartDate', title: '合同开始日期', format: 'date' },\n { name: 'contractEndDate', title: '合同结束日期', format: 'date' },\n { name: 'probationPeriod', title: '试用期状态', render: value => <Tag color=\"success\">{value}</Tag> }\n ]}\n />\n </InfoPage.Part>\n\n <InfoPage.Part bordered title=\"福利待遇\" subtitle=\"薪资与福利\">\n <CentralContent\n type=\"compact\"\n dataSource={{\n baseSalary: 30000,\n performanceBonus: 5000,\n annualBonus: 50000,\n socialInsurance: '已缴纳(五险一金)',\n housingFund: 3600,\n medicalInsurance: '已包含',\n mealAllowance: 1500,\n transportAllowance: 800,\n stockOptions: 5000,\n otherBenefits: '年度体检、节日礼品、团建活动'\n }}\n col={2}\n columns={[\n { name: 'baseSalary', title: '基本月薪', format: 'number-useGrouping:true-suffix:元', span: 12 },\n { name: 'performanceBonus', title: '绩效奖金', format: 'number-useGrouping:true-suffix:元/月', span: 12 },\n { name: 'annualBonus', title: '年终奖金', format: 'number-useGrouping:true-suffix:元', block: true },\n { name: 'socialInsurance', title: '社会保险', render: value => <Tag color=\"success\">{value}</Tag> },\n { name: 'housingFund', title: '公积金', format: 'number-useGrouping:true-suffix:元/月' },\n { name: 'medicalInsurance', title: '医疗保险', render: value => <Tag color=\"success\">{value}</Tag> },\n { name: 'mealAllowance', title: '餐补', format: 'number-useGrouping:true-suffix:元/月' },\n { name: 'transportAllowance', title: '交通补贴', format: 'number-useGrouping:true-suffix:元/月' },\n { name: 'stockOptions', title: '股票期权', format: 'number-useGrouping:true-suffix:股', block: true },\n { name: 'otherBenefits', title: '其他福利', block: true }\n ]}\n />\n </InfoPage.Part>\n\n <InfoPage.Part bordered title=\"放在Modal中\">\n <Button\n onClick={() => {\n setOpen(true);\n }}>\n 打开Modal\n </Button>\n <Modal title=\"员工档案\" open={open} onCancel={()=>setOpen(false)}>{baseInfo}</Modal>\n </InfoPage.Part>\n </InfoPage>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `表格视图`,\n description: `支持行选择、固定表头和多数据展示的表格组件`,\n code: `const { TableView } = _InfoPage;\nconst { Flex, Tag, Badge } = antd;\nconst { useState } = React;\n\nconst dataSource = [\n {\n id: 'ORD20240115001',\n customerName: '深圳市腾讯计算机系统有限公司',\n contact: '张三',\n phone: '138-0013-8000',\n amount: 42500,\n status: '已完成',\n orderDate: '2024-01-15',\n deliveryDate: '2024-01-17'\n },\n {\n id: 'ORD20240115002',\n customerName: '华为技术有限公司',\n contact: '李四',\n phone: '139-0014-9000',\n amount: 85000,\n status: '处理中',\n orderDate: '2024-01-15',\n deliveryDate: '2024-01-20'\n },\n {\n id: 'ORD20240115003',\n customerName: '阿里巴巴集团控股有限公司',\n contact: '王五',\n phone: '137-0015-7000',\n amount: 120000,\n status: '待发货',\n orderDate: '2024-01-14',\n deliveryDate: '2024-01-22'\n },\n {\n id: 'ORD20240115004',\n customerName: '北京字节跳动科技有限公司',\n contact: '赵六',\n phone: '136-0016-6000',\n amount: 65000,\n status: '已完成',\n orderDate: '2024-01-13',\n deliveryDate: '2024-01-16'\n },\n {\n id: 'ORD20240115005',\n customerName: '百度在线网络技术(北京)有限公司',\n contact: '钱七',\n phone: '135-0017-5000',\n amount: 95000,\n status: '已取消',\n orderDate: '2024-01-12',\n deliveryDate: ''\n }\n];\n\nconst columns = [\n { name: 'id', title: '订单编号' },\n { name: 'customerName', title: '客户名称', span: 10 },\n { name: 'contact', title: '联系人' },\n { name: 'phone', title: '联系电话', render: (value) => value.replace(/(\\d{3})(\\d{4})(\\d{4})/, '\\$1-\\$2-\\$3') },\n { name: 'amount', title: '订单金额(元)', render: (value) => <strong style={{ color: '#f5222d' }}>¥{value.toLocaleString()}</strong> },\n { name: 'orderDate', title: '下单日期', format: 'date' },\n { name: 'deliveryDate', title: '预计送达', format: 'date' },\n { name: 'status', title: '订单状态', render: (value) => {\n const config = {\n '已完成': { color: 'success', text: '已完成' },\n '处理中': { color: 'processing', text: '处理中' },\n '待发货': { color: 'warning', text: '待发货' },\n '已取消': { color: 'default', text: '已取消' }\n };\n const { color, text } = config[value] || { color: 'default', text: value };\n return <Badge status={color} text={text} />;\n }}\n];\n\nconst WithCheckbox = () => {\n const [selectKeys, setSelectKeys] = useState([]);\n const totalAmount = selectKeys.reduce((sum, id) => sum + (dataSource.find(d => d.id === id)?.amount || 0), 0);\n return (\n <div>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 12 }}>\n <span>已选 <strong>{selectKeys.length}</strong> 个订单,总金额 <strong style={{ color: '#52c41a' }}>¥{totalAmount.toLocaleString()}</strong></span>\n </Flex>\n <TableView dataSource={dataSource} columns={columns} rowSelection={{\n type: 'checkbox', allowSelectedAll: true, selectedRowKeys: selectKeys, onChange: setSelectKeys\n }} />\n </div>\n );\n};\n\nconst WithSelected = () => {\n const [selectKeys, setSelectKeys] = useState([]);\n const selectedOrder = dataSource.find(d => d.id === selectKeys[0]);\n return (\n <div>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 12 }}>\n <span>已选订单:{selectedOrder ? \\`\\${selectedOrder.id} (\\${selectedOrder.customerName})\\` : '无'}</span>\n {selectedOrder && <Tag color=\"blue\">¥{selectedOrder.amount.toLocaleString()}</Tag>}\n </Flex>\n <TableView dataSource={dataSource} columns={columns} rowSelection={{\n type: 'radio', selectedRowKeys: selectKeys, onChange: setSelectKeys\n }} />\n </div>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Flex vertical gap={16}>\n <div style={{ background: '#f5f5f5', padding: '12px', borderRadius: '8px' }}>\n 订单列表 - 共 <strong>{dataSource.length}</strong> 个订单\n </div>\n <TableView dataSource={dataSource} columns={columns} />\n <WithCheckbox />\n <WithSelected />\n <div style={{ padding: '16px', background: '#fafafa', border: '1px dashed #d9d9d9', borderRadius: '8px' }}>\n 暂无订单数据\n </div>\n <TableView\n style={{ height: '250px', overflowY: 'scroll' }}\n dataSource={dataSource}\n columns={columns}\n sticky\n headerStyle={{ position: 'sticky', top: 0, zIndex: 1, background: '#fafafa' }}\n />\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `表格选择`,\n description: `展示TableView组件的各种选择模式`,\n code: `const { TableView } = _InfoPage;\nconst { Flex, Radio, Space, Button, Tag, Avatar } = antd;\nconst { useState } = React;\n\nconst dataSource = [\n { id: 'C20240115001', name: '张三', company: '腾讯科技', contact: '138-0013-8000', amount: 50000, status: '已签约' },\n { id: 'C20240115002', name: '李四', company: '华为技术', contact: '139-0014-9000', amount: 85000, status: '跟进中' },\n { id: 'C20240115003', name: '王五', company: '阿里巴巴', contact: '137-0015-7000', amount: 120000, status: '已签约' },\n { id: 'C20240115004', name: '赵六', company: '字节跳动', contact: '136-0016-6000', amount: 65000, status: '待跟进' },\n { id: 'C20240115005', name: '钱七', company: '百度在线', contact: '135-0017-5000', amount: 95000, status: '已签约' }\n];\n\nconst columns = [\n { name: 'id', title: '客户编号' },\n { name: 'name', title: '联系人' },\n { name: 'company', title: '所属公司' },\n { name: 'contact', title: '联系电话' },\n { name: 'amount', title: '签约金额(元)' },\n { name: 'status', title: '状态' }\n];\n\nconst BaseExample = () => {\n const [selectionType, setSelectionType] = useState('none');\n const [selectedRowKeys, setSelectedRowKeys] = useState([]);\n\n // 复选框选择示例\n const CheckboxExample = () => {\n const [keys, setKeys] = useState([]);\n const totalAmount = keys.reduce((sum, id) => sum + (dataSource.find(d => d.id === id)?.amount || 0), 0);\n return (\n <div>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 12 }}>\n <span>已选 <strong style={{ color: '#1890ff' }}>{keys.length}</strong> 位客户,总金额 <strong style={{ color: '#52c41a' }}>¥{totalAmount.toLocaleString()}</strong></span>\n <Space>\n <Button size=\"small\" onClick={() => setKeys(dataSource.filter(d => d.status === '已签约').map(d => d.id))}>\n 选已签约\n </Button>\n <Button size=\"small\" onClick={() => setKeys([])}>清空</Button>\n </Space>\n </Flex>\n <TableView\n dataSource={dataSource}\n columns={columns}\n rowSelection={{\n type: 'checkbox',\n selectedRowKeys: keys,\n onChange: setKeys\n }}\n />\n </div>\n );\n };\n\n // 全选状态示例\n const SelectAllExample = () => {\n const [keys, setKeys] = useState([]);\n const [isSelectedAll, setIsSelectedAll] = useState(false);\n\n const handleSelectAll = () => {\n if (isSelectedAll) {\n setKeys([]);\n } else {\n setKeys(dataSource.map(d => d.id));\n }\n setIsSelectedAll(!isSelectedAll);\n };\n\n return (\n <div>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 12 }}>\n <span>{isSelectedAll ? <Tag color=\"green\">已全选所有客户</Tag> : <Tag>未全选</Tag>}</span>\n <Button size=\"small\" onClick={handleSelectAll}>\n {isSelectedAll ? '取消全选' : '全选客户'}\n </Button>\n </Flex>\n <TableView\n dataSource={dataSource}\n columns={columns}\n rowSelection={{\n type: 'checkbox',\n isSelectedAll,\n allowSelectedAll: true,\n selectedRowKeys: keys,\n onChange: (keys) => {\n setKeys(keys);\n setIsSelectedAll(keys.length === dataSource.length);\n }\n }}\n />\n </div>\n );\n };\n\n // 单选框示例\n const RadioExample = () => {\n const [key, setKey] = useState(null);\n const selectedCustomer = dataSource.find(d => d.id === key);\n return (\n <div>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 12 }}>\n <span>已选客户:{selectedCustomer ? \\`\\${selectedCustomer.name} (\\${selectedCustomer.company})\\` : '无'}</span>\n <Tag color={selectedCustomer ? 'blue' : 'default'}>{selectedCustomer ? \\`¥\\${selectedCustomer.amount.toLocaleString()}\\` : '-'}</Tag>\n </Flex>\n <TableView\n dataSource={dataSource}\n columns={columns}\n rowSelection={{\n type: 'radio',\n selectedRowKeys: key ? [key] : [],\n onChange: (keys) => setKey(keys.length > 0 ? keys[0] : null)\n }}\n />\n </div>\n );\n };\n\n // 无选择模式\n const NoSelectionExample = () => (\n <div>\n <div style={{ marginBottom: 12 }}>客户列表 - 共 {dataSource.length} 位</div>\n <TableView dataSource={dataSource} columns={columns} />\n </div>\n );\n\n // 自定义渲染示例\n const CustomRenderExample = () => {\n const [keys, setKeys] = useState([]);\n return (\n <div>\n <div style={{ marginBottom: 12 }}>自定义渲染客户列表</div>\n <TableView\n dataSource={dataSource}\n columns={[\n { name: 'id', title: '客户编号' },\n { name: 'name', title: '联系人', render: (value) => <Flex align=\"center\" gap={8}><Avatar size=\"small\">{value[0]}</Avatar>{value}</Flex> },\n { name: 'company', title: '所属公司' },\n { name: 'contact', title: '联系电话' },\n { name: 'amount', title: '签约金额', render: (value) => <strong style={{ color: '#52c41a' }}>¥{value.toLocaleString()}</strong> },\n { name: 'status', title: '状态', render: (value) => {\n const config = {\n '已签约': { color: 'success', text: '已签约' },\n '跟进中': { color: 'processing', text: '跟进中' },\n '待跟进': { color: 'warning', text: '待跟进' }\n };\n const { color, text } = config[value] || { color: 'default', text: value };\n return <Tag color={color}>{text}</Tag>;\n }}\n ]}\n rowSelection={{\n type: 'checkbox',\n selectedRowKeys: keys,\n onChange: setKeys\n }}\n />\n </div>\n );\n };\n\n const renderExample = () => {\n switch (selectionType) {\n case 'checkbox':\n return <CheckboxExample />;\n case 'selectAll':\n return <SelectAllExample />;\n case 'radio':\n return <RadioExample />;\n case 'custom':\n return <CustomRenderExample />;\n default:\n return <NoSelectionExample />;\n }\n };\n\n return (\n <Flex vertical gap={16}>\n {/* 控制面板 */}\n <div style={{ background: '#f5f5f5', padding: '16px', borderRadius: '8px' }}>\n <span style={{ marginRight: 12 }}>选择模式:</span>\n <Radio.Group value={selectionType} onChange={(e) => setSelectionType(e.target.value)}>\n <Radio.Button value=\"none\">无选择</Radio.Button>\n <Radio.Button value=\"checkbox\">复选框</Radio.Button>\n <Radio.Button value=\"selectAll\">全选状态</Radio.Button>\n <Radio.Button value=\"radio\">单选框</Radio.Button>\n <Radio.Button value=\"custom\">自定义渲染</Radio.Button>\n </Radio.Group>\n </div>\n\n {/* 示例展示区 */}\n {renderExample()}\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `分割线展示`,\n description: `支持图标和垂直/横向布局的紧凑信息展示`,\n code: `const { SplitLine } = _InfoPage;\nconst { Flex, Tag, Avatar } = antd;\nconst { MobileOutlined, CompassOutlined, MailOutlined, TeamOutlined, CalendarOutlined, EnvironmentOutlined } = antdIcons;\n\nconst BaseExample = () => {\n return (\n <Flex vertical gap={20}>\n {/* 个人信息展示 - 水平布局 */}\n <div>\n <h4 style={{ marginBottom: 12, color: '#333' }}>员工卡片</h4>\n <SplitLine wrap\n dataSource={{\n name: '张三',\n position: '高级前端工程师',\n department: '技术研发部',\n phone: '138-0013-8000',\n email: 'zhangsan@tencent.com',\n workYears: 4,\n entryDate: '2020-03-15',\n status: '在职'\n }}\n columns={[\n {\n name: 'name',\n title: '姓名',\n render: (value) => (\n <Flex align=\"center\" gap={8}>\n <Avatar style={{ backgroundColor: '#1890ff' }}>{value[0]}</Avatar>\n <strong>{value}</strong>\n </Flex>\n )\n },\n {\n name: 'position',\n title: '职位',\n render: (value) => <Tag color=\"blue\">{value}</Tag>\n },\n {\n name: 'department',\n title: '部门',\n render: (value) => <Tag color=\"cyan\">{value}</Tag>\n },\n {\n name: 'phone',\n title: '联系电话',\n icon: <MobileOutlined />,\n render: (value) => value.replace(/(\\d{3})(\\d{4})(\\d{4})/, '\\$1-\\$2-\\$3')\n },\n {\n name: 'email',\n title: '电子邮箱',\n icon: <MailOutlined />\n },\n {\n name: 'workYears',\n title: '工作年限',\n icon: <CalendarOutlined />,\n render: (value) => \\`\\${value}年\\`\n },\n {\n name: 'entryDate',\n title: '入职日期',\n icon: <CalendarOutlined />,\n render: (value) => value\n },\n {\n name: 'status',\n title: '状态',\n render: (value) => <Tag color=\"success\">{value}</Tag>\n }\n ]}\n />\n </div>\n\n {/* 公司信息展示 - 垂直布局 */}\n <div>\n <h4 style={{ marginBottom: 12, color: '#333' }}>公司信息</h4>\n <SplitLine wrap\n labelMode=\"vertical\"\n dataSource={{\n companyName: '深圳市腾讯计算机系统有限公司',\n creditCode: '914403007109410773',\n legalPerson: '马化腾',\n registerDate: '1998-11-11',\n capital: '500万美元',\n address: '深圳市南山区高新科技园科技中一路腾讯大厦',\n businessScope: '计算机软硬件的技术开发、销售;计算机网络工程;系统集成;软件开发及技术服务;信息咨询;网络设备、通讯设备、电子产品的技术开发与销售;国内贸易。'\n }}\n columns={[\n {\n name: 'companyName',\n title: '企业名称'\n },\n {\n name: 'creditCode',\n title: '统一社会信用代码',\n icon: <TeamOutlined />\n },\n {\n name: 'legalPerson',\n title: '法定代表人'\n },\n {\n name: 'registerDate',\n title: '成立日期',\n icon: <CalendarOutlined />\n },\n {\n name: 'capital',\n title: '注册资本'\n },\n {\n name: 'address',\n title: '注册地址',\n icon: <EnvironmentOutlined />\n },\n {\n name: 'businessScope',\n title: '经营范围'\n }\n ]}\n />\n </div>\n\n {/* 项目信息展示 */}\n <div>\n <h4 style={{ marginBottom: 12, color: '#333' }}>项目详情</h4>\n <SplitLine wrap\n dataSource={{\n projectName: '企业级管理系统重构',\n projectCode: 'PRJ-2024-001',\n manager: '张三',\n teamSize: 12,\n startDate: '2024-01-01',\n endDate: '2024-06-30',\n progress: 35,\n budget: 1500000,\n spent: 525000\n }}\n columns={[\n {\n name: 'projectName',\n title: '项目名称'\n },\n {\n name: 'projectCode',\n title: '项目编号'\n },\n {\n name: 'manager',\n title: '项目经理',\n icon: <TeamOutlined />\n },\n {\n name: 'teamSize',\n title: '团队规模',\n render: (value) => \\`\\${value}人\\`\n },\n {\n name: 'startDate',\n title: '开始日期',\n icon: <CalendarOutlined />\n },\n {\n name: 'endDate',\n title: '结束日期',\n icon: <CalendarOutlined />\n },\n {\n name: 'progress',\n title: '项目进度',\n render: (value) => <Tag color={value >= 100 ? 'success' : 'processing'}>{value}%</Tag>\n },\n {\n name: 'budget',\n title: '项目预算',\n render: (value) => \\`¥\\${value.toLocaleString()}\\`\n },\n {\n name: 'spent',\n title: '已投入',\n render: (value) => \\`¥\\${value.toLocaleString()}\\`\n }\n ]}\n />\n </div>\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_82\n},{\n name: \"antdIcons\",\n packageName: \"@ant-design/icons\",\n component: component_83\n}]\n},{\n title: `流程步骤`,\n description: `支持自定义渲染和多种状态的流程时序展示组件`,\n code: `const { Flex, Space, Divider, Tag } = antd;\nconst { Flow } = _InfoPage;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size={24} style={{ width: '100%' }}>\n {/* 基础流程示例 */}\n <div>\n <Divider orientation=\"left\">请假审批流程</Divider>\n <Flow\n current={1}\n dataSource={[\n { title: '提交申请', description: '2024-01-15 09:00 张三提交请假申请', status: 'finish' },\n { title: '部门审批', description: '等待李经理审批', status: 'process' },\n { title: '人事审核', description: '待人事部审核', status: 'wait' },\n { title: '流程结束', description: '审批流程完成', status: 'wait' }\n ]}\n />\n </div>\n\n {/* 带副标题的流程 */}\n <div>\n <Divider orientation=\"left\">订单处理流程</Divider>\n <Flow\n current={2}\n dataSource={[\n { title: '创建订单', subTitle: '2024-01-15 09:30', status: 'finish' },\n { title: '支付成功', subTitle: '2024-01-15 10:15', status: 'finish' },\n { title: '仓库发货', subTitle: '2024-01-15 14:00', status: 'finish' },\n { title: '配送中', subTitle: '2024-01-16 08:30', status: 'process' },\n { title: '已签收', subTitle: '待确认', status: 'wait' }\n ]}\n />\n </div>\n\n {/* 使用 columns 自定义渲染 */}\n <div>\n <Divider orientation=\"left\">项目审批流程</Divider>\n <Flow\n dataSource={[\n {\n title: '需求评审',\n description: '通过',\n operator: '张产品',\n time: '2024-01-15 09:00',\n logs: [\n { name: '张产品', action: '提交需求文档', time: '2024-01-15 09:00', content: '包含功能列表、技术方案、时间计划' },\n { name: '李技术', action: '技术评审通过', time: '2024-01-15 11:00', content: '技术方案可行,资源充足' }\n ]\n },\n {\n title: '开发实施',\n description: '进行中',\n operator: '王开发',\n time: '2024-01-16 09:00',\n logs: [\n { name: '王开发', action: '开始开发', time: '2024-01-16 09:00', content: '前端和后端并行开发' }\n ]\n },\n {\n title: '测试验收',\n description: '待处理',\n operator: '赵测试',\n time: '2024-01-20 00:00',\n logs: []\n }\n ]}\n columns={[\n { name: 'title' },\n { name: 'description', render: (value) => <Tag color={value === '通过' ? 'success' : value === '进行中' ? 'processing' : 'default'}>{value}</Tag> },\n { type: 'subTitle', name: 'time', format: 'datetime' },\n {\n type: 'actionList',\n name: 'logs',\n children: [\n { name: 'name' },\n { name: 'action' },\n { type: 'options', name: 'time', format: 'datetime' },\n { name: 'content' }\n ]\n }\n ]}\n />\n </div>\n\n {/* 点状步骤条 */}\n <div>\n <Divider orientation=\"left\">项目里程碑</Divider>\n <Flex gap={16}>\n <div style={{ flex: 1 }}>\n <p style={{ marginBottom: 8, color: '#666' }}>垂直时间轴</p>\n <Flow\n direction=\"vertical\"\n progressDot\n dataSource={[\n { title: '项目启动', description: '2024-01-01', status: 'finish' },\n { title: '需求分析', description: '2024-01-15', status: 'finish' },\n { title: '系统设计', description: '2024-02-01', status: 'process' },\n { title: '开发实施', description: '2024-03-01', status: 'wait' },\n { title: '测试上线', description: '2024-04-01', status: 'wait' }\n ]}\n />\n </div>\n <div style={{ flex: 1 }}>\n <p style={{ marginBottom: 8, color: '#666' }}>水平进度条</p>\n <Flow\n direction=\"horizontal\"\n progressDot\n dataSource={[\n { title: '注册', description: '完成', status: 'finish' },\n { title: '验证', description: '完成', status: 'finish' },\n { title: '审核', description: '进行中', status: 'process' },\n { title: '通过', description: '待办', status: 'wait' }\n ]}\n />\n </div>\n </Flex>\n </div>\n\n {/* 使用 content 类型自定义内容 */}\n <div>\n <Divider orientation=\"left\">合同审批流程</Divider>\n <Flow\n dataSource={[\n {\n title: '草拟阶段',\n description: '法务部',\n content: '合同条款已草拟完成,包含保密协议、付款条款、违约责任等内容。',\n status: 'finish'\n },\n {\n title: '业务审核',\n description: '业务部门',\n content: '业务部门已确认合同内容,符合业务需求。',\n status: 'finish'\n },\n {\n title: '财务审核',\n description: '财务部',\n content: '财务部正在审核付款条款和预算安排,预计2个工作日完成。',\n status: 'process'\n },\n {\n title: '最终签署',\n description: '等待',\n content: '',\n status: 'wait'\n }\n ]}\n columns={[\n {\n type: 'content',\n name: 'content',\n render: (item) => (\n <div style={{ background: '#f9f9f9', padding: '12px', borderRadius: '4px', fontSize: '13px', lineHeight: '1.6' }}>\n {item}\n </div>\n )\n }\n ]}\n />\n </div>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `报告页面`,\n description: `完整的测评报告生成组件,支持评分、表格和详细描述`,\n code: `const { Report } = _InfoPage;\nconst { Space } = antd;\nconst BaseExample = () => {\n return (\n <div className=\"outer\">\n <Space direction=\"vertical\" size={24}>\n <Report title=\"报告概述\">\n <Report.List\n report={{\n list: [\n {\n label: '目的',\n content: '本报告旨在评估招聘顾问使用AI工具进行候选人初次沟通的能力,特别是在理解候选人需求、传达职位信息以及建立初步信任关系的效果。'\n },\n {\n label: '测评对象',\n content: '姓名:张伟'\n },\n {\n label: '测评工具',\n content: \\`AI模拟系统:提供基于语音和文本的交互模拟环境。\\n评分标准:沟通技巧、信息传达清晰度、候选人反馈、建立关系的能力。\\`\n },\n {\n label: '任务目标',\n content: (\n <ul>\n <li>完整呈现初次沟通话术,展现每个关键动作和沟通顺序。</li>\n <li>收集候选人信息:了解候选人工作背景,技术能力及其薪资要求。</li>\n <li>挖掘需求:全面了解候选人求职动态和需求,从而掌握候选人存在的顾虑及。</li>\n <li>有效推荐:根据候选人求职需求链接职位优势,强化技术吸引点,妥善处理候选人疑虑。</li>\n <li>建立信任关系:使用沟通技巧,态度诚恳,和候选人站在一起,而非“博弈”关系。</li>\n </ul>\n )\n }\n ]\n }}\n />\n </Report>\n <Report title=\"测评结果\">\n <Report.Result\n report={{\n total: {\n score: '81.8',\n label: '综合得分'\n },\n list: [\n {\n label: '沟通程序指引及话术',\n score: '86',\n content:\n '张伟在这一部分的表现总体上是专业且有条理的,能够按照一定的流程顺利开展对话。他表现出的礼貌和专业性在询问是否方便通话时得到了完美的体现,得到了满分。然而,他在介绍职位时未能充分利用机会强调职位的吸引点,可能影响候选人的兴趣。'\n },\n {\n label: '收集信息(现状\\$&\\$期望)',\n score: '90',\n content: '张伟在收集候选人的现状和期望方面做得相对完善,能够获得关于候选人当前工作和技术栈的重要信息。但对于候选人的项目经验和薪资结构的探讨不够深入,这可能会影响到后续的职位匹配和期望管理。'\n },\n {\n label: '挖掘需求',\n score: '70',\n content: '张伟在挖掘候选人需求方面还有提升空间。虽然基本了解了候选人的职业期望,但在探索候选人的非薪酬动机和深层次需求方面表现不够充分,这是建立有效推荐和深度关系的关键。'\n },\n {\n label: '有效推荐',\n score: '73',\n content: '在有效推荐职位方面,张伟需要加强与候选人需求的匹配度和说服力。虽然提到了职位的技术优势,但未根据候选人的具体技术背景进行个性化强调,可能减少候选人的兴趣。'\n },\n {\n label: '建立信任关系',\n score: '84',\n content: '张伟能够通过有效的沟通建立信任关系,使用开放性问题和积极肯定候选人的表现。然而,需要提高在换位思考和理解候选人深层需求方面的能力,确保信任关系的深度和真实性。'\n }\n ]\n }}\n />\n </Report>\n <Report title=\"评分细节\">\n <Report.Table\n report={{\n columns: [\n {\n title: '评估维度',\n name: 'group',\n isSubTitle: true\n },\n {\n title: '评分项',\n name: 'item',\n span: 10\n },\n {\n title: '得分',\n name: 'score',\n span: 4,\n valueOf: value => <div className=\"score\">{value}</div>\n },\n {\n title: '描述',\n name: 'description',\n span: 10\n }\n ],\n group: [\n {\n name: 'group1',\n label: '沟通程序指引及话术'\n },\n {\n name: 'group2',\n label: '收集信息(现状&期望)'\n },\n {\n name: 'group3',\n label: '挖掘需求'\n },\n {\n name: 'group4',\n label: '有效推荐'\n },\n {\n name: 'group5',\n label: '建立信任关系'\n }\n ],\n list: [\n {\n group: 'group1',\n item: '专业开场',\n score: <Report.Score value={4}/>,\n description: '开场专业,语气友好,略显急促。'\n },\n {\n group: 'group1',\n item: '询问是否方便通话',\n score: <Report.Score value={5}/>,\n description: '表现出极好的礼貌和考虑。'\n },\n {\n group: 'group1',\n item: '先了解候选人整体情况',\n score: <Report.Score value={3}/>,\n description: '详细询问了技术和动机,未深入个人发展。'\n },\n {\n group: 'group1',\n item: '后介绍推荐OD职位',\n score: <Report.Score value={4}/>,\n description: '介绍清晰,未充分突出职位吸引力。'\n },\n {\n group: 'group1',\n item: '介绍整体面试流程',\n score: <Report.Score value={1}/>,\n description: '详尽介绍流程,缺少机考准备细节说明。'\n },\n {\n group: 'group1',\n item: '交换联系方式',\n score: <Report.Score value={5}/>,\n description: '有效且自然,确保双方畅通无阻。'\n },\n {\n group: 'group2',\n item: '了解候选人目前就业状态',\n score: <Report.Score value={5}/>,\n description: '详尽了解候选人的当前就业状况。'\n },\n {\n group: 'group2',\n item: '了解候选人技术栈及项目经验',\n score: <Report.Score value={4}/>,\n description: '详细询问技术栈,对项目经验探讨不足。'\n },\n {\n group: 'group2',\n item: '了解候选人薪资情况与结构',\n score: <Report.Score value={4}/>,\n description: '了解薪资期望清晰,未详细探讨薪资构成。'\n },\n {\n group: 'group3',\n item: '了解候选人对下一份工作的期望',\n score: <Report.Score value={3}/>,\n description: '探讨了职业规划,但未深挖发展意愿。'\n },\n {\n group: 'group3',\n item: '探索非薪资求职动机',\n score: <Report.Score value={2}/>,\n description: '基本了解求职动机,缺乏深度和细节。'\n },\n {\n group: 'group3',\n item: '识别并处理顾虑',\n score: <Report.Score value={4}/>,\n description: '识别了顾虑,回应稍显模糊。'\n },\n {\n group: 'group4',\n item: '链接职位优势与求职动机',\n score: <Report.Score value={3}/>,\n description: '提及职位相关性,缺乏说服力。'\n },\n {\n group: 'group4',\n item: '强化项目技术吸引点',\n score: <Report.Score value={3}/>,\n description: '提及技术优势,未针对候选人背景定制。'\n },\n {\n group: 'group4',\n item: '关注并处理候选人顾虑',\n score: <Report.Score value={4}/>,\n description: '正面回应顾虑,但解决方案不具体。'\n },\n {\n group: 'group5',\n item: '应用开放性提问',\n score: <Report.Score value={0}/>,\n description: '使用开放性问题促进了对话深入。'\n },\n {\n group: 'group5',\n item: '换位思考与表达同理心',\n score: <Report.Score value={1}/>,\n description: '表达了同理心,但部分回答未完全站在候选人角度。'\n },\n {\n group: 'group5',\n item: '表达肯定和欣赏',\n score: <Report.Score value={5}/>,\n description: '非常好地肯定了候选人的能力和经验。'\n },\n {\n group: 'group5',\n item: '清晰表达观点',\n score: <Report.Score value={2}/>,\n description: '观点主要清晰,偶有不够准确的情况。'\n },\n {\n group: 'group5',\n item: '有效倾听与理解',\n score: <Report.Score value={3}/>,\n description: '倾听良好,但有时未能完全抓住候选人的意图。'\n }\n ]\n }}\n />\n </Report>\n <Report title=\"结论与建议\">\n <Report.Part\n report={{\n list: [\n {\n label: '结论',\n hasBgColor: true,\n content:\n '在此次AI情景模拟测评中,李四表现出了较强的沟通能力和专业性,尤其是在程序指引及话术方面。他成功地收集了候选人的基本信息并建立了初步的信任关系。然而,他在深入挖掘候选人需求和个性化推荐职位方面的表现还有待提高。总体而言,李四的表现良好,显示出了他作为招聘顾问的潜力。'\n },\n {\n label: '建议',\n style: { '--marker-color': '#027A48', '--label-bg-color': '#027A481a' },\n content: (\n <ol>\n <li>增强职位介绍的吸引力,特别是将职位优势与候选人的需求直接关联,突出表现职位的独特之处。</li>\n <li>对候选人的项目经验进行更详细的询问,尤其是关于如何在项目中解决问题和技术应用的具体情况。</li>\n <li>在讨论薪资时,应详细了解候选人的薪资构成和期望,确保提供的职位与候选人的薪资期望相匹配。</li>\n <li>在交流中穿插探讨候选人的个人兴趣和长期职业目标,以便更好地理解其动机。</li>\n <li>根据候选人的技术能力和职业兴趣定制职位推荐,突出职位的技术挑战和成长机会。</li>\n <li>加强同理心的表达,尤其在讨论候选人关切的问题时,从其角度出发提供解决方案。</li>\n </ol>\n )\n }\n ]\n }}\n />\n </Report>\n <Report title=\"结论与建议\">自定义 area</Report>\n </Space>\n </div>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `报告组件`,\n description: `展示Report的各子组件:List、Result、Table、Part`,\n code: `const { Report, Score } = _InfoPage;\nconst { Flex, Radio, Space } = antd;\nconst { useState } = React;\n\nconst reportData = {\n total: {\n score: '88.5',\n label: '综合评分'\n },\n list: [\n {\n label: '代码质量',\n score: '95',\n content: '代码风格规范,注释清晰完整,遵循ESLint和Prettier规范。组件拆分合理,复用性强,单元测试覆盖率达到85%。代码审查中提出的修改意见响应及时,整改完成率高。'\n },\n {\n label: '技术深度',\n score: '90',\n content: '深入理解React源码原理,熟悉Hooks工作机制和性能优化技巧。对前端工程化、微前端架构有实践经验。在项目中成功实现SSR方案,提升首屏渲染速度60%。'\n },\n {\n label: '团队协作',\n score: '85',\n content: '积极参与代码评审和技术讨论,乐于分享技术心得。与产品、设计、测试团队沟通顺畅,能够准确理解需求并给出合理的技术建议。协助新同事快速融入团队。'\n },\n {\n label: '创新意识',\n score: '82',\n content: '主动探索新技术,将AI辅助开发工具引入团队,提升开发效率约20%。提出多个优化方案并被采纳,为业务增长做出了贡献。持续关注行业动态,技术敏感度高。'\n }\n ]\n};\n\nconst tableReportData = {\n columns: [\n { title: '评估维度', name: 'group', isSubTitle: true, span: 24 },\n { title: '评估项', name: 'item', span: 12 },\n { title: '得分', name: 'score', span: 4 },\n { title: '说明', name: 'description', span: 8 }\n ],\n group: [\n { name: 'group1', label: '📌 核心技术能力' },\n { name: 'group2', label: '💼 工作业绩' },\n { name: 'group3', label: '🎯 职业素养' }\n ],\n list: [\n { group: 'group1', item: '前端框架', score: <Score value={5} total={5} />, description: 'React/Vue熟练掌握' },\n { group: 'group1', item: 'TypeScript', score: <Score value={5} total={5} />, description: '类型定义规范完整' },\n { group: 'group1', item: '性能优化', score: <Score value={4} total={5} />, description: 'SSR首屏优化显著' },\n { group: 'group1', item: '工程化', score: <Score value={4} total={5} />, description: 'CI/CD流程完善' },\n { group: 'group2', item: '需求交付', score: <Score value={5} total={5} />, description: '按时交付率98%' },\n { group: 'group2', item: '质量保障', score: <Score value={4} total={5} />, description: '线上故障率低' },\n { group: 'group2', item: '文档输出', score: <Score value={3} total={5} />, description: 'API文档需完善' },\n { group: 'group3', item: '团队协作', score: <Score value={5} total={5} />, description: '沟通顺畅主动' },\n { group: 'group3', item: '学习成长', score: <Score value={4} total={5} />, description: '技术分享积极' },\n { group: 'group3', item: '责任意识', score: <Score value={5} total={5} />, description: '工作认真负责' }\n ],\n footer: (item, index) => (\n <div style={{ padding: '4px 0', color: '#999', fontSize: '12px' }}>\n 第 {index + 1} 项\n </div>\n )\n};\n\nconst listReportData = {\n list: [\n { label: '👤 评估对象', content: '王明远' },\n { label: '🏢 所属部门', content: '技术研发中心 - 前端架构组' },\n { label: '💼 职级职位', content: '资深前端工程师(P6+)' },\n { label: '📅 入职时间', content: '2021年3月15日' },\n { label: '📊 评估周期', content: '2024年度' },\n { label: '🔍 评估日期', content: '2025年1月10日' },\n { label: '👨💼 评估人', content: '技术总监 - 陈思远' },\n { label: '📋 评估维度', content: '核心技能、项目绩效、职业素养' },\n { label: '🔧 评估方法', content: '代码审查 + 绩效数据 + 360度评估 + 技术面试' }\n ]\n};\n\nconst partReportData = {\n list: [\n {\n label: '✨ 核心优势',\n hasBgColor: true,\n content: '1. 技术视野开阔,对前端技术栈有系统性理解,能够从架构层面思考问题。2. 学习能力强,快速掌握新技术并转化为生产力,AI工具应用效果显著。3. 代码质量意识强,注重可维护性和扩展性,推动团队代码规范落地。4. 工作积极主动,主动承担复杂任务,多次解决关键技术难题。'\n },\n {\n label: '📈 成长空间',\n content: '1. 在技术管理和团队带领方面需要更多历练。2. 跨部门协作时的商业思维有待提升,需要更好地理解业务价值。3. 技术成果的可视化展示和影响力打造可以进一步加强。'\n },\n {\n label: '🎯 发展建议',\n content: '1. 争取担任小型项目的Tech Lead,积累团队管理经验。2. 加强对后端、运维相关技术的学习,建立全栈技术视角。3. 每季度组织至少一次技术分享,提升团队技术氛围。4. 参与技术面试和人才评估,锻炼识人用人能力。5. 关注行业前沿趋势,定期输出技术文章或开源贡献。'\n },\n {\n label: '📚 培养计划',\n content: '1. Q2参加技术管理进阶培训。2. Q3参与微服务架构专项学习。3. Q4承担新人导师角色。4. 全年参与至少3个技术峰会或工作坊。5. 建立个人技术博客,每月至少输出1篇技术文章。'\n }\n ]\n};\n\nconst BaseExample = () => {\n const [componentType, setComponentType] = useState('list');\n\n const renderComponent = () => {\n switch (componentType) {\n case 'list':\n return <Report.List report={listReportData} />;\n case 'result':\n return <Report.Result report={reportData} />;\n case 'table':\n return <Report.Table report={tableReportData} />;\n case 'part':\n return <Report.Part report={partReportData} />;\n default:\n return <Report.List report={listReportData} />;\n }\n };\n\n return (\n <Flex vertical gap={16}>\n {/* 控制面板 */}\n <div style={{ background: '#f5f5f5', padding: '16px', borderRadius: '8px' }}>\n <span style={{ marginRight: 12 }}>子组件类型:</span>\n <Radio.Group value={componentType} onChange={(e) => setComponentType(e.target.value)}>\n <Radio.Button value=\"list\">Report.List</Radio.Button>\n <Radio.Button value=\"result\">Report.Result</Radio.Button>\n <Radio.Button value=\"table\">Report.Table</Radio.Button>\n <Radio.Button value=\"part\">Report.Part</Radio.Button>\n </Radio.Group>\n </div>\n\n {/* 组件展示区 */}\n <Space direction=\"vertical\" size={24}>\n <Report title=\"📄 员工年度绩效评估报告\" subtitle=\"2024年度 | 技术研发中心 | 前端架构组\">\n {renderComponent()}\n </Report>\n </Space>\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `评分展示`,\n description: `支持自定义总分和间距的星级评分组件`,\n code: `const { Score } = _InfoPage;\nconst { Flex, Badge, Card, Divider, Tag, Space } = antd;\n\nconst BaseExample = () => {\n return (\n <Flex vertical gap={16}>\n {/* 基础用法 */}\n <Card title=\"基础评分\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Flex gap={24} align=\"center\">\n <span>产品评分:</span>\n <Score value={5} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>服务质量:</span>\n <Score value={4} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>物流速度:</span>\n <Score value={3} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>性价比:</span>\n <Score value={2} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>用户满意:</span>\n <Score value={1} />\n </Flex>\n </Space>\n </Card>\n\n <Divider />\n\n {/* 自定义总分 */}\n <Card title=\"自定义总分\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Flex gap={24} align=\"center\">\n <span>3分制:</span>\n <Score value={0} total={3} />\n <Score value={1} total={3} />\n <Score value={2} total={3} />\n <Score value={3} total={3} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>4分制:</span>\n <Score value={1} total={4} />\n <Score value={2} total={4} />\n <Score value={3} total={4} />\n <Score value={4} total={4} />\n </Flex>\n <Flex gap={24} align=\"center\">\n <span>5分制:</span>\n <Score value={2} total={5} />\n <Score value={3} total={5} />\n <Score value={4} total={5} />\n <Score value={5} total={5} />\n </Flex>\n </Space>\n </Card>\n\n <Divider />\n\n {/* 无间距 */}\n <Card title=\"紧凑模式(gap=0)\" size=\"small\">\n <Flex gap={24} align=\"center\">\n <Score value={1} total={5} gap={0} />\n <Score value={2} total={5} gap={0} />\n <Score value={3} total={5} gap={0} />\n <Score value={4} total={5} gap={0} />\n <Score value={5} total={5} gap={0} />\n </Flex>\n </Card>\n\n <Divider />\n\n {/* 业务场景 */}\n <Card title=\"业务场景示例\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div style={{ padding: '8px 0' }}>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 8 }}>\n <span>商品名称</span>\n <Tag color=\"blue\">新品上市</Tag>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 4 }}>\n <span style={{ color: '#999', fontSize: 12 }}>用户评价</span>\n <Badge count={128} showZero />\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ fontSize: 14, fontWeight: 500 }}>Apple iPhone 15 Pro</span>\n <Score value={5} />\n </Flex>\n </div>\n\n <div style={{ padding: '8px 0', borderTop: '1px solid #f0f0f0' }}>\n <Flex justify=\"space-between\" align=\"center\" style={{ marginBottom: 4 }}>\n <span style={{ color: '#999', fontSize: 12 }}>商品评分</span>\n <span style={{ fontSize: 12, color: '#ff4d4f' }}>4.8/5.0</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ fontSize: 14 }}>综合得分</span>\n <Score value={4} total={5} />\n </Flex>\n </div>\n </Space>\n </Card>\n\n <Divider />\n\n {/* 所有评分展示 */}\n <Card title=\"完整评分展示\" size=\"small\">\n <Flex wrap=\"wrap\" gap={16}>\n {Array.from({ length: 6 }).map((_, index) => (\n <Flex key={index} vertical align=\"center\" gap={4}>\n <Score value={index} />\n <span style={{ fontSize: 12, color: '#999' }}>{index}分</span>\n </Flex>\n ))}\n </Flex>\n </Card>\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n},{\n title: `格式化视图`,\n description: `展示formatView工具函数的各种格式化用法`,\n code: `const { formatView } = _InfoPage;\nconst { Flex, Space, Tag, Badge } = antd;\n\n// 演示 formatView 工具函数的使用\nconst FormatDemo = () => {\n const demoData = {\n orderDate: '2024-01-15T10:30:00',\n deliveryDate: '2024-01-20',\n serviceDateRange: ['2024-01-01', '2024-12-31'],\n isVip: true,\n isActivated: false,\n userCount: 15678,\n totalAmount: 99999.99,\n discountRate: 0.085,\n completionRate: 85.67,\n phoneNumber: '13800138000'\n };\n\n // 自定义格式化函数\n const formatPhone = (val) => {\n if (!val) return '-';\n return val.replace(/(\\d{3})(\\d{4})(\\d{4})/, '\\$1-\\$2-\\$3');\n };\n\n return (\n <Flex vertical gap={16}>\n <div style={{ background: '#f5f5f5', padding: '16px', borderRadius: '8px' }}>\n <h4 style={{ margin: '0 0 12px 0' }}>formatView 工具函数演示</h4>\n <Space direction=\"vertical\" size={8} style={{ width: '100%' }}>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>datetime:</strong></span>\n <span>{formatView(demoData.orderDate, 'datetime')} → {formatView(demoData.orderDate, 'datetime-YYYY年MM月DD日 HH:mm')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>date:</strong></span>\n <span>{formatView(demoData.deliveryDate, 'date')} → {formatView(demoData.deliveryDate, 'date-YYYY/MM/DD')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>dateRange:</strong></span>\n <span>{formatView(demoData.serviceDateRange, 'dateRange')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>boolean:</strong></span>\n <Flex gap={8}>\n <span>VIP客户: {formatView(demoData.isVip, 'boolean-是/否')}</span>\n <span>已激活: {formatView(demoData.isActivated, 'boolean-是/否')}</span>\n </Flex>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>number:</strong></span>\n <span>{formatView(demoData.userCount, 'number-useGrouping:true')} 用户</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>money:</strong></span>\n <span style={{ color: '#f5222d', fontWeight: 'bold' }}>{formatView(demoData.totalAmount, 'money-元')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>discount:</strong></span>\n <span>折扣: {formatView(demoData.discountRate * 100, 'number-maximumFractionDigits:1-suffix:折')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>percent:</strong></span>\n <span>完成率: {formatView(demoData.completionRate, 'number-maximumFractionDigits:2-suffix:%')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span><strong>custom:</strong></span>\n <span>{formatPhone(demoData.phoneNumber)}</span>\n </Flex>\n </Space>\n </div>\n\n {/* 实际应用场景演示 */}\n <div style={{ background: '#fff', padding: '16px', borderRadius: '8px', border: '1px solid #e8e8e8' }}>\n <h4 style={{ margin: '0 0 12px 0' }}>实际应用场景:订单详情</h4>\n <Flex vertical gap={8}>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>订单编号</span>\n <span>ORD20240115001</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>下单时间</span>\n <span>{formatView(demoData.orderDate, 'datetime')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>预计送达</span>\n <span>{formatView(demoData.deliveryDate, 'date-YYYY年MM月DD日')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>服务期限</span>\n <span>{formatView(demoData.serviceDateRange, 'dateRange')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>客户类型</span>\n <Tag color={demoData.isVip ? 'gold' : 'default'}>{formatView(demoData.isVip, 'boolean-VIP/普通')}</Tag>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>订单金额</span>\n <span style={{ color: '#f5222d', fontSize: '18px', fontWeight: 'bold' }}>\n {formatView(demoData.totalAmount, 'money-元')}\n </span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>优惠折扣</span>\n <span style={{ color: '#52c41a' }}>{formatView(demoData.discountRate * 100, 'number-maximumFractionDigits:1-suffix:折')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>订单状态</span>\n <Badge status={demoData.completionRate >= 100 ? 'success' : 'processing'} text={demoData.completionRate >= 100 ? '已完成' : '处理中'} />\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>完成进度</span>\n <span>{formatView(demoData.completionRate, 'number-maximumFractionDigits:2-suffix:%')}</span>\n </Flex>\n <Flex justify=\"space-between\" align=\"center\">\n <span style={{ color: '#666' }}>联系电话</span>\n <span>{formatPhone(demoData.phoneNumber)}</span>\n </Flex>\n </Flex>\n </div>\n </Flex>\n );\n};\n\nconst BaseExample = () => {\n return (\n <Flex vertical gap={24}>\n <FormatDemo />\n </Flex>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_InfoPage\",\n packageName: \"@kne/info-page\",\n component: component_71\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_73\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_65 from '@components/Layout';\nimport * as component_66 from '@components/Global';\nimport * as component_67 from 'antd';\nimport * as component_68 from '@components/Filter';\nconst readmeConfig = {\n name: `Layout`,\n summary: `<p>Layout 是一个完整的页面布局框架,为登录后的系统页面提供统一的布局结构和样式规范。它将页面划分为多个区域,包括导航区、内容区、左菜单区、右操作区、页头区、页头信息区、页面标题区等,通过灵活的配置可以组合出不同布局风格的页面。</p>\n<p><strong>核心特性</strong></p>\n<ul>\n<li><strong>统一布局</strong>:提供标准化的页面布局结构,确保系统页面风格统一</li>\n<li><strong>灵活配置</strong>:通过 Page 组件的参数配置不同区域的显示和样式</li>\n<li><strong>性能优化</strong>:页面参数通过 Context 保存,页面跳转时非页面区域走更新周期而非挂载周期,提升渲染速度</li>\n<li><strong>区域划分</strong>:支持导航区、内容区、左菜单区、右操作区、页头区、页头信息区、页面标题区等多种区域</li>\n<li><strong>权限集成</strong>:内置权限判断,支持 PermissionsPage 快速实现权限控制</li>\n<li><strong>组件丰富</strong>:提供 Page、Menu、PageHeader、TablePage、StateBarPage 等多个子组件满足不同需求</li>\n</ul>\n<p><strong>适用场景</strong></p>\n<ul>\n<li><strong>基础页面</strong>:简单的上下布局,导航栏+内容区</li>\n<li><strong>左侧菜单页</strong>:带有左侧导航菜单的页面,支持多级菜单</li>\n<li><strong>筛选列表页</strong>:顶部带筛选器的列表页面</li>\n<li><strong>详情页</strong>:带有页面头和额外信息的详情页面</li>\n<li><strong>表格页</strong>:快速集成 Table 组件的列表页面</li>\n<li><strong>状态栏页</strong>:带有状态栏的状态展示页面</li>\n</ul>\n<p><strong>重要说明</strong></p>\n<ul>\n<li>Page 组件的 <code>name</code> 参数必须传递,用于页面跳转时判断是否为同一页面,决定是否走挂载周期</li>\n<li>请尽量通过 Page 提供的参数配置页面布局,避免自定义 CSS,以便 Layout 组件统一控制页面形式和样式</li>\n<li>Page 组件参数通过 Context 保存,页面跳转时非页面区域会走更新周期,提升性能</li>\n</ul>`,\n \n \n api: `<h3>Layout</h3>\n<p>Layout 组件是页面布局的容器组件,包裹所有页面内容并提供统一的布局结构。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>navigation</td>\n<td>object</td>\n<td>否</td>\n<td>{}</td>\n<td>导航参数,参考 Navigation 组件参数</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>是</td>\n<td>-</td>\n<td>子组件,一般放置 Page 组件</td>\n</tr>\n<tr>\n<td>className</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>自定义类名</td>\n</tr>\n<tr>\n<td>theme</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>主题样式配置</td>\n</tr>\n</tbody>\n</table>\n<h3>Page</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>menu</td>\n<td>左菜单区内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>filter</td>\n<td>页面标题位置筛选器参数,参考 Filter 组件参数</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>menuOpen</td>\n<td>左菜单是否默认打开</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>menuWidth</td>\n<td>左菜单宽度</td>\n<td>string</td>\n<td>240px</td>\n</tr>\n<tr>\n<td>menuFixed</td>\n<td>左菜单是否fixed布局</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>menuCloseButton</td>\n<td>控制左菜单显示隐藏的按钮是否显示</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>header</td>\n<td>页头区内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>headerFixed</td>\n<td>页头区是否fixed布局</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>headerInfo</td>\n<td>页头信息区内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>backUrl</td>\n<td>右侧内容区的标题前展示返回按钮,并返回到该url</td>\n<td>参考 useNavigate</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>页面标题</td>\n<td>string,jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>titleExtra</td>\n<td>页面标题区右侧位置内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>titleLeftExtra</td>\n<td>页面标题区左侧位置内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>noMargin</td>\n<td>页面内容区是否去掉Margin</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>noPadding</td>\n<td>页面内容区是否去掉Padding</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>option</td>\n<td>右操作区内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>optionWidth</td>\n<td>右操作区宽度</td>\n<td>string</td>\n<td>400px</td>\n</tr>\n<tr>\n<td>optionNoPadding</td>\n<td>右操作区是否去掉Padding</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>optionFixed</td>\n<td>右操作区是否fixed布局</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>optionFooter</td>\n<td>右操作区底部内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>openFeatures</td>\n<td>Page是否启用Features,启用时如果配置文件中没有该模块id则判断为模块关闭,会将name作为Features的id进行设置</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<h3>Affix</h3>\n<p>可以控制其中的内容是否是fixed布局</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>isFixed</td>\n<td>内容是否fixed布局</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>offsetTop</td>\n<td>距离窗口顶部达到指定偏移量后触发</td>\n<td>number</td>\n<td>0</td>\n</tr>\n<tr>\n<td>offsetBottom</td>\n<td>距离窗口底部达到指定偏移量后触发</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>固定状态改变时触发的回调函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>Menu</h3>\n<p>显示一个菜单,最多支持两级,支持第一级展开收起,支持路径匹配自动高亮</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>items</td>\n<td>菜单项</td>\n<td>array[object]</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>items[].label</td>\n<td>菜单项显示内容</td>\n<td>jsx</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].key</td>\n<td>菜单项的key要求必须唯一</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].iconType</td>\n<td>菜单项前面的icon类型参考 Icon组件的type参数</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].path</td>\n<td>菜单项的路径</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].onClick</td>\n<td>菜单项点击触发事件,注意:如果菜单项已经传入path参数则该参数不生效</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].children</td>\n<td>菜单项的第二级项列表,参考items参数。注意该组件只支持两级菜单,所以该参数内部的菜单项不再支持children参数</td>\n<td>array[object]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>currentKey</td>\n<td>当前被选中的菜单项的key,如果菜单项又path参数,不需要传递该参数,组件会根据路由自动判断选中项</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>currentKey产生修改时触发函数,注意:如果菜单项已经传入path参数则该参数不生效</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>allowCollapsed</td>\n<td>是否允许一级菜单收起</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>defaultOpenKeys</td>\n<td>初始展开的 SubMenu 菜单项 key 数组</td>\n<td>string[]</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>PermissionsPage</h3>\n<p>加入权限判断的 Page 组件,错误类型默认为 error,即在该页面没有权限时显示错误。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>permissions</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>权限配置,参考 Permissions 组件参数</td>\n</tr>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>页面名称,必填</td>\n</tr>\n<tr>\n<td>openFeatures</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否启用 Features 功能特性</td>\n</tr>\n</tbody>\n</table>\n<p>注意:PermissionsPage 继承了 Page 的所有属性。</p>\n<h3>TablePage</h3>\n<p>快速集成 Table 组件的列表页面,内置了权限控制和帮助文档支持。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>helperGuideName</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>帮助文档的名称</td>\n</tr>\n<tr>\n<td>permissions</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>权限配置,参考 Permissions 组件参数</td>\n</tr>\n<tr>\n<td>page</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>Page 组件的配置参数</td>\n</tr>\n<tr>\n<td>openFeatures</td>\n<td>boolean</td>\n<td>否</td>\n<td>false</td>\n<td>是否启用 Features 功能特性</td>\n</tr>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>是</td>\n<td>-</td>\n<td>页面名称,必填</td>\n</tr>\n<tr>\n<td>topArea</td>\n<td>ReactNode | function</td>\n<td>否</td>\n<td>-</td>\n<td>顶部额外内容区,可以是组件或函数(接收 tableData 参数)</td>\n</tr>\n</tbody>\n</table>\n<p>注意:除了以上属性,TablePage 还支持 Table 组件的所有属性(如 columns、api、pagination 等)。</p>\n<h3>StateBarPage</h3>\n<p>带有状态栏的状态展示页面,内置了权限控制和帮助文档支持。</p>\n<h4>属性说明</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>类型</th>\n<th>必填</th>\n<th>默认值</th>\n<th>说明</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>helperGuideName</td>\n<td>string</td>\n<td>否</td>\n<td>-</td>\n<td>帮助文档的名称</td>\n</tr>\n<tr>\n<td>permissions</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>权限配置,参考 Permissions 组件参数</td>\n</tr>\n<tr>\n<td>page</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>Page 组件的配置参数</td>\n</tr>\n<tr>\n<td>stateBar</td>\n<td>object</td>\n<td>否</td>\n<td>-</td>\n<td>StateBar 组件的配置参数</td>\n</tr>\n<tr>\n<td>children</td>\n<td>ReactNode</td>\n<td>否</td>\n<td>-</td>\n<td>页面内容区</td>\n</tr>\n</tbody>\n</table>\n<p>注意:除了以上属性,StateBarPage 还继承了 Page 的所有属性。</p>`,\n example: {\n isFull: true,\n className: `Layout_ebd9b`,\n style: `.Layout_ebd9b .layout-content {\n color: #fff;\n background: var(--primary-color-4);\n height: 100%;\n text-align: center;\n line-height: 300px;\n}\n.Layout_ebd9b .with-title-layout-content {\n height: 100%;\n}\n.Layout_ebd9b .layout-menu {\n background: #ff9c6e;\n color: #fff;\n height: 110vh;\n text-align: center;\n line-height: 300px;\n}\n.Layout_ebd9b .header {\n background: #ff9c6e;\n height: 100px;\n padding: 10px;\n color: #fff;\n}\n.Layout_ebd9b .right-options {\n background: var(--primary-color-4);\n height: 110vh;\n color: #fff;\n}\n.Layout_ebd9b .header-info {\n padding: 10px;\n height: 100px;\n background: var(--primary-color-4);\n color: #fff;\n}`,\n list: [{\n title: `基础上下布局`,\n description: `展示最基础的上导航栏,下内容的布局`,\n code: `const { default: Layout, Page } = _Layout;\nconst { PureGlobal } = global;\nconst BaseExample = () => {\n return (\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"base-detail\",\n content: \"测试帮助文档\",\n url: \"/\",\n },\n ],\n },\n }}\n >\n <Layout navigation={{ isFixed: false }}>\n <Page name=\"base\" helperGuideName=\"base-detail\">\n <div className=\"layout-content\">内容区</div>\n </Page>\n </Layout>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n}]\n},{\n title: `带有左侧菜单布局`,\n description: `展示带有左侧菜单布局`,\n code: `const { default: Layout, Page, Menu } = layout;\nconst { Button, Space } = antd;\nconst { PureGlobal } = global;\n\nconst Example = () => {\n return (\n <Layout navigation={{ isFixed: false }}>\n <Page\n name=\"left-menu\"\n menuFixed={false}\n menu={\n <Menu\n items={[\n {\n label: \"父级标题1\",\n key: \"p-0\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-0\",\n path: \"/link1\",\n },\n {\n label: \"子标题2\",\n key: \"s-1\",\n path: \"/link2\",\n },\n ],\n },\n {\n label: \"父级标题2\",\n key: \"p-1\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-2\",\n path: \"/link3\",\n },\n {\n label: \"子标题2\",\n key: \"s-3\",\n path: \"/link4\",\n },\n ],\n },\n {\n label: \"父级标题3\",\n key: \"p-2\",\n iconType: \"icon-zhanghaodenglu\",\n path: \"/link5\",\n },\n ]}\n />\n }\n titleExtra={\n <Space>\n <Button type=\"primary\">新建</Button>\n </Space>\n }\n backUrl={\"/\"}\n title=\"标题\"\n >\n <div className=\"layout-content with-title-layout-content\">内容区</div>\n </Page>\n </Layout>\n );\n};\n\nrender(\n <PureGlobal>\n <Example />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n}]\n},{\n title: `左侧固定带Header`,\n description: `展示带有header的左侧固定菜单布局`,\n code: `const { default: Layout, Page } = layout;\nconst { Button, Space } = antd;\nconst { PureGlobal } = global;\n\nconst Example = () => {\n return (\n <Space className=\"container\" direction=\"vertical\">\n <Layout navigation={{ isFixed: false }}>\n <Page\n name=\"with-header\"\n helperGuideName=\"base-detail\"\n menu={<div className=\"layout-menu\">左侧菜单区</div>}\n titleExtra={\n <Space>\n <Button type=\"primary\">新建</Button>\n </Space>\n }\n title=\"标题\"\n hideCloseSvg={true}\n headerHeight=\"40px\"\n menuFixed={false}\n header={<div className=\"header\">header</div>}\n headerFixed={false}\n headerInfo={<div className=\"header-info\">header info区域</div>}\n >\n <div>内容区</div>\n </Page>\n </Layout>\n </Space>\n );\n};\n\nrender(\n <PureGlobal\n preset={{\n enums: {\n helperGuide: () => [\n {\n value: \"base-detail\",\n content: \"测试帮助文档\",\n url: \"/\",\n },\n ],\n },\n }}\n >\n <Example />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n}]\n},{\n title: `右侧固定`,\n description: `展示带有header的右侧固定菜单布局`,\n code: `const { default: Layout, Page } = layout;\nconst { Button, Space } = antd;\nconst { PureGlobal } = global;\n\nconst Example = () => {\n return (\n <Layout navigation={{ isFixed: false }}>\n <Page\n name=\"fix-right-menu\"\n optionFixed={false}\n option={<div className=\"right-options\">右侧操作区域</div>}\n optionFooter={\n <Space>\n <Button type=\"primary\">新建</Button>\n </Space>\n }\n titleExtra={\n <Space>\n <Button type=\"primary\">新建</Button>\n </Space>\n }\n title=\"标题\"\n header={<div className=\"header\">header</div>}\n headerFixed={false}\n menuFixed={false}\n >\n <div>内容区</div>\n </Page>\n </Layout>\n );\n};\n\nrender(\n <PureGlobal>\n <Example />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n}]\n},{\n title: `带有filter的列表页`,\n description: `展示带有filter的列表页`,\n code: `const { default: Layout, Page } = layout;\nconst {\n InputFilterItem,\n CityFilterItem,\n AdvancedSelectFilterItem,\n UserFilterItem,\n FunctionSelectFilterItem,\n IndustrySelectFilterItem,\n getFilterValue,\n} = filter;\nconst { useState } = React;\nconst { Space, Button } = antd;\nconst { PureGlobal } = global;\nconst BaseExample = () => {\n const [filter, setFilter] = useState([]);\n return (\n <PureGlobal preset={{}}>\n <Layout navigation={{ isFixed: false }}>\n <Page\n name=\"base\"\n helperGuideName=\"base-detail\"\n titleExtra={\n <Space>\n <Button type=\"primary\">添加</Button>\n </Space>\n }\n filter={{\n extraExpand: (\n <Button type=\"primary\" size=\"small\">\n 订阅筛选项\n </Button>\n ),\n value: filter,\n onChange: (value) => {\n setFilter(value);\n console.log(getFilterValue(value));\n },\n list: [\n [\n <InputFilterItem label=\"文字\" name=\"text\" />,\n <CityFilterItem label=\"城市\" name=\"city\" />,\n <AdvancedSelectFilterItem\n label=\"高级选择\"\n name=\"select\"\n api={{\n loader: () => {\n return {\n pageData: [\n { label: \"第一项\", value: 1 },\n { label: \"第二项\", value: 2, disabled: true },\n {\n label: \"第三项\",\n value: 3,\n },\n ],\n };\n },\n }}\n />,\n <UserFilterItem\n label=\"用户选择\"\n name=\"user\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n {\n label: \"用户三\",\n value: 3,\n description: \"我是用户描述\",\n },\n ],\n };\n },\n }}\n />,\n <FunctionSelectFilterItem\n label=\"职能选择\"\n name=\"function\"\n onlyAllowLastLevel\n single\n />,\n <IndustrySelectFilterItem\n label=\"行业选择\"\n name=\"industry\"\n onlyAllowLastLevel\n />,\n ],\n [\n <UserFilterItem\n label=\"职位协助人\"\n name=\"position_user\"\n api={{\n loader: () => {\n return {\n pageData: [\n {\n label: \"用户一\",\n value: 1,\n description: \"我是用户描述\",\n },\n {\n label: \"用户二\",\n value: 2,\n description: \"我是用户描述\",\n },\n {\n label: \"用户三\",\n value: 3,\n description: \"我是用户描述\",\n },\n ],\n };\n },\n }}\n />,\n ],\n ],\n }}\n >\n <div className=\"layout-content\">内容区</div>\n </Page>\n </Layout>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n},{\n name: \"filter\",\n packageName: \"@components/Filter\",\n component: component_68\n}]\n},{\n title: `左侧导航菜单`,\n description: `展示一个左侧导航菜单`,\n code: `const { Menu } = layout;\nconst { Space } = antd;\nconst { useState } = React;\n\nconst ControlMenu = () => {\n const [current, setCurrent] = useState();\n return (\n <Menu\n currentKey={current}\n onChange={setCurrent}\n items={[\n {\n label: \"父级标题1\",\n key: \"p-0\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-0\",\n },\n {\n label: \"子标题2\",\n key: \"s-1\",\n },\n ],\n },\n {\n label: \"父级标题2\",\n key: \"p-1\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-2\",\n },\n {\n label: \"子标题2\",\n key: \"s-3\",\n },\n ],\n },\n {\n label: \"父级标题3\",\n key: \"p-2\",\n iconType: \"icon-zhanghaodenglu\",\n },\n ]}\n />\n );\n};\n\nconst Example = () => {\n return (\n <Space size={10}>\n <Menu\n items={[\n {\n label: \"父级标题1\",\n key: \"p-0\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-0\",\n path: \"/link1\",\n },\n {\n label: \"子标题2\",\n key: \"s-1\",\n path: \"/link2\",\n },\n ],\n },\n {\n label: \"父级标题2\",\n key: \"p-1\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-2\",\n path: \"/link3\",\n },\n {\n label: \"子标题2\",\n key: \"s-3\",\n path: \"/link4\",\n },\n ],\n },\n {\n label: \"父级标题3\",\n key: \"p-2\",\n iconType: \"icon-zhanghaodenglu\",\n path: \"/link5\",\n },\n ]}\n />\n <Menu\n items={[\n {\n iconType: \"icon-zhanghaodenglu\",\n label: \"子标题1\",\n key: \"s-0\",\n path: \"/link1\",\n },\n {\n iconType: \"icon-zhanghaodenglu\",\n label: \"子标题2\",\n key: \"s-1\",\n path: \"/link2\",\n },\n {\n iconType: \"icon-zhanghaodenglu\",\n label: \"子标题1\",\n key: \"s-2\",\n path: \"/link3\",\n },\n {\n iconType: \"icon-zhanghaodenglu\",\n label: \"子标题2\",\n key: \"s-3\",\n path: \"/link4\",\n },\n ]}\n />\n <Menu\n allowCollapsed={false}\n items={[\n {\n label: \"父级标题1\",\n key: \"p-0\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-0\",\n path: \"/link1\",\n },\n {\n label: \"子标题2\",\n key: \"s-1\",\n path: \"/link2\",\n },\n ],\n },\n {\n label: \"父级标题2\",\n key: \"p-1\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"子标题1\",\n key: \"s-2\",\n path: \"/link3\",\n },\n {\n label: \"子标题2\",\n key: \"s-3\",\n path: \"/link4\",\n },\n ],\n },\n {\n label: \"父级标题3\",\n key: \"p-2\",\n iconType: \"icon-zhanghaodenglu\",\n path: \"/link5\",\n },\n ]}\n />\n <ControlMenu />\n </Space>\n );\n};\n\nrender(<Example />);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `PageHeader`,\n description: `页面头`,\n code: `const { default: Layout, Page, Menu, PageHeader } = layout;\n\nconst Example = () => {\n return (\n <Layout navigation={{ isFixed: false }}>\n <Page\n menu={<div className=\"layout-menu\">左侧菜单区</div>}\n title=\"标题\"\n hideCloseSvg={true}\n menuFixed={false}\n name=\"pageHeaderLayout\"\n header={\n <PageHeader\n iconType=\"icon-color-shenpi-biaoti\"\n title=\"详情页名称\"\n info=\"编号:85767\"\n options={[\n {\n children: \"新建\",\n },\n {\n children: \"操作1\",\n },\n {\n children: \"操作2\",\n },\n {\n children: \"操作3\",\n },\n {\n children: \"操作4\",\n },\n ]}\n tags={[\"辅助信息\", \"辅助信息\", \"辅助信息\", \"辅助信息\"]}\n />\n }\n headerFixed={false}\n >\n <div>内容区</div>\n </Page>\n </Layout>\n );\n};\n\nrender(<Example />);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `Affix 固定布局`,\n description: `展示 Affix 组件的固定布局功能`,\n code: `const { default: Layout, Affix } = _Layout;\nconst { Space, Card, Button, Typography } = antd;\n\nconst { Text } = Typography;\n\nconst AffixExample = () => {\n const [fixed, setFixed] = React.useState(false);\n\n return (\n <Layout navigation={{ isFixed: false }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"Affix 固定布局组件\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <Text strong>固定到顶部(offsetTop: 100):</Text>\n <div style={{ marginTop: 16 }}>\n <Affix offsetTop={100} onChange={(fixed) => setFixed(fixed)}>\n <div style={{\n background: 'var(--primary-color)',\n color: 'white',\n padding: '16px 24px',\n borderRadius: '4px',\n textAlign: 'center',\n width: '200px'\n }}>\n 我会在距离顶部 100px 时固定\n {fixed && ' (已固定)'}\n </div>\n </Affix>\n </div>\n </div>\n\n <div style={{ marginTop: 32 }}>\n <Text strong>不固定(isFixed: false):</Text>\n <div style={{ marginTop: 16 }}>\n <Affix isFixed={false}>\n <div style={{\n background: 'var(--state-warning-color)',\n color: 'white',\n padding: '16px 24px',\n borderRadius: '4px',\n textAlign: 'center',\n width: '200px'\n }}>\n 我不会被固定\n </div>\n </Affix>\n </div>\n </div>\n </Space>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n Affix 组件用于控制内容的固定布局行为,基于 Antd 的 Affix 组件进行了封装。\n </Text>\n <Text type=\"secondary\">\n 当 isFixed 为 true 时,内容会在滚动到指定位置后固定显示;\n 当 isFixed 为 false 时,内容固定行为被禁用。\n </Text>\n </Space>\n </Card>\n\n <div style={{ height: 800 }}>\n <Text type=\"secondary\">(向下滚动查看 Affix 固定效果)</Text>\n </div>\n </Space>\n </Layout>\n );\n};\n\nrender(<AffixExample />);\n\n`,\n scope: [{\n name: \"_Layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `TablePage 表格页面`,\n description: `展示 TablePage 组件快速创建表格列表页`,\n code: `const {default: Layout, TablePage} = _Layout;\nconst {PureGlobal} = global;\nconst {Button} = antd;\n\nconst TablePageExample = () => {\n const columns = [{\n title: '订单号', name: 'orderNo'\n }, {\n title: '客户姓名', name: 'customerName'\n }, {\n title: '金额', name: 'amount', render: (amount) => \\`¥\\${amount.toLocaleString()}\\`\n }, {\n title: '状态', name: 'status'\n }, {\n title: '创建时间', name: 'createTime'\n }];\n\n return (<PureGlobal preset={{\n enums: {\n helperGuide: () => [{\n value: 'order-list-help',\n content: '这是一个订单列表页面,可以查看和管理所有订单信息。',\n url: 'https://example.com/help/order-list'\n }]\n }\n }}>\n <Layout navigation={{isFixed: false}}>\n <TablePage\n name=\"order-list\"\n helperGuideName=\"order-list-help\"\n page={{\n title: '订单列表', titleExtra: <Button type=\"primary\">新建订单</Button>\n }}\n columns={columns}\n loader={() => {\n return {\n pageData: [{\n key: '1',\n orderNo: 'ORD202401001',\n customerName: '张三',\n amount: 1200.00,\n status: '已完成',\n createTime: '2024-01-15 10:30:00'\n }, {\n key: '2',\n orderNo: 'ORD202401002',\n customerName: '李四',\n amount: 3500.00,\n status: '处理中',\n createTime: '2024-01-15 11:20:00'\n }, {\n key: '3',\n orderNo: 'ORD202401003',\n customerName: '王五',\n amount: 890.00,\n status: '待处理',\n createTime: '2024-01-15 14:45:00'\n }], total: 3\n };\n }}\n topArea={(tableData) => (<div style={{padding: '16px', background: '#fafafa', marginBottom: '16px'}}>\n <div>数据统计:共 {tableData?.pageData?.length || 0} 条记录</div>\n </div>)}\n />\n </Layout>\n </PureGlobal>);\n};\n\nrender(<TablePageExample/>);\n\n`,\n scope: [{\n name: \"_Layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `StateBarPage 状态栏页面`,\n description: `展示 StateBarPage 组件创建带状态栏的页面`,\n code: `const { default: Layout, StateBarPage } = _Layout;\nconst { PureGlobal } = global;\nconst { Card, Descriptions, Button, Space, Typography } = antd;\n\nconst { Text } = Typography;\n\nconst StateBarPageExample = () => {\n return (\n <PureGlobal preset={{\n enums: {\n helperGuide: () => [{\n value: 'order-detail-help',\n content: '这是一个订单详情页面,可以查看和管理订单详情信息。',\n url: 'https://example.com/help/order-detail'\n }]\n }\n }}>\n <Layout navigation={{ isFixed: false }}>\n <StateBarPage\n name=\"order-detail\"\n helperGuideName=\"order-detail-help\"\n page={{\n title: '订单详情',\n titleExtra: (\n <Space>\n <Button>编辑</Button>\n <Button type=\"primary\">导出</Button>\n </Space>\n )\n }}\n stateBar={{\n list: [\n {\n label: '全部',\n value: 'all',\n count: 100\n },\n {\n label: '待处理',\n value: 'pending',\n count: 25\n },\n {\n label: '处理中',\n value: 'processing',\n count: 30\n },\n {\n label: '已完成',\n value: 'completed',\n count: 40\n },\n {\n label: '已取消',\n value: 'cancelled',\n count: 5\n }\n ],\n onChange: (value) => {\n console.log('状态切换:', value);\n }\n }}\n >\n <Card title=\"订单信息\" size=\"small\">\n <Descriptions column={2} bordered>\n <Descriptions.Item label=\"订单号\">ORD202401001</Descriptions.Item>\n <Descriptions.Item label=\"客户姓名\">张三</Descriptions.Item>\n <Descriptions.Item label=\"订单金额\">¥1,200.00</Descriptions.Item>\n <Descriptions.Item label=\"创建时间\">2024-01-15 10:30:00</Descriptions.Item>\n <Descriptions.Item label=\"收货地址\" span={2}>\n 北京市朝阳区某某街道123号\n </Descriptions.Item>\n <Descriptions.Item label=\"订单备注\" span={2}>\n 用户要求尽快发货\n </Descriptions.Item>\n </Descriptions>\n </Card>\n </StateBarPage>\n </Layout>\n </PureGlobal>\n );\n};\n\nrender(<StateBarPageExample />);\n\n`,\n scope: [{\n name: \"_Layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `PermissionsPage 权限页面`,\n description: `展示 PermissionsPage 组件的权限控制功能`,\n code: `const { default: Layout, PermissionsPage } = _Layout;\nconst { PureGlobal } = global;\nconst { Card, Button, Space, Typography, Alert } = antd;\n\nconst { Text } = Typography;\n\nconst PermissionsPageExample = () => {\n return (\n <PureGlobal\n preset={{\n permissions: ['order:view', 'order:edit', 'order:delete']\n }}\n >\n <Layout navigation={{ isFixed: false }}>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Card title=\"有权限访问的页面\" size=\"small\">\n <PermissionsPage\n name=\"order-detail-with-perm\"\n permissions={{\n permissions: ['order:view']\n }}\n page={{\n title: '订单详情(有权限)'\n }}\n >\n <Alert\n message=\"您有权限访问此页面\"\n description=\"当前用户拥有 order:view 权限,可以查看订单详情\"\n type=\"success\"\n showIcon\n style={{ marginBottom: 16 }}\n />\n <Card size=\"small\">\n <Text>这里是订单详情内容</Text>\n </Card>\n </PermissionsPage>\n </Card>\n\n <Card title=\"无权限访问的页面\" size=\"small\">\n <PermissionsPage\n name=\"order-edit-without-perm\"\n permissions={{\n permissions: ['order:edit:advanced']\n }}\n page={{\n title: '订单编辑(无权限)'\n }}\n >\n <Alert\n message=\"您不会看到这个内容\"\n description=\"因为当前用户没有 order:edit:advanced 权限\"\n type=\"info\"\n showIcon\n />\n <Card size=\"small\">\n <Text>这里不会显示,因为缺少权限</Text>\n </Card>\n </PermissionsPage>\n </Card>\n\n <Card title=\"说明\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">\n PermissionsPage 组件在 Page 的基础上增加了权限判断功能。\n </Text>\n <Text type=\"secondary\">\n 如果用户没有所需权限,会显示错误提示页面,不会渲染页面内容。\n </Text>\n <Text type=\"secondary\">\n 权限通过 preset.permissions 配置,组件内部会自动检查是否拥有所需权限。\n </Text>\n </Space>\n </Card>\n </Space>\n </Layout>\n </PureGlobal>\n );\n};\n\nrender(<PermissionsPageExample />);\n\n`,\n scope: [{\n name: \"_Layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n}]\n},{\n title: `移动端适配`,\n description: `展示 Layout 组件的移动端响应式适配功能,菜单在移动端以Drawer形式显示`,\n code: `const { default: Layout, Page, Menu } = layout;\nconst { Flex, Space, Button, Typography, Card, Descriptions } = antd;\nconst { PureGlobal } = global;\nconst { useState } = React;\nconst { Title, Paragraph } = Typography;\n\nconst MobileExample = () => {\n const [isMobile, setIsMobile] = useState(true);\n\n return (\n <Layout\n navigation={{\n isFixed: false,\n list: [\n {key: 'dashboard', title: '首页', path: '/dashboard'},\n {key: 'users', title: '用户管理', path: '/users'},\n {key: 'settings', title: '系统设置', path: '/settings'}\n ]\n }}\n isMobile={isMobile}\n >\n <Page\n name=\"mobile-example\"\n menuFixed={false}\n menu={\n <Menu\n items={[\n {\n label: \"组织架构\",\n key: \"org\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"部门管理\",\n key: \"dept\",\n path: \"/dept\",\n },\n {\n label: \"员工管理\",\n key: \"employee\",\n path: \"/employee\",\n },\n ],\n },\n {\n label: \"业务管理\",\n key: \"business\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"订单管理\",\n key: \"order\",\n path: \"/order\",\n },\n {\n label: \"客户管理\",\n key: \"customer\",\n path: \"/customer\",\n },\n {\n label: \"产品管理\",\n key: \"product\",\n path: \"/product\",\n },\n ],\n },\n {\n label: \"数据报表\",\n key: \"report\",\n iconType: \"icon-zhanghaodenglu\",\n children: [\n {\n label: \"销售报表\",\n key: \"sales-report\",\n path: \"/sales-report\",\n },\n {\n label: \"财务报表\",\n key: \"finance-report\",\n path: \"/finance-report\",\n },\n ],\n },\n ]}\n />\n }\n title=\"组织管理\"\n titleExtra={\n <Space>\n <Button\n type={isMobile ? 'primary' : 'default'}\n onClick={() => setIsMobile(true)}\n >\n 移动端\n </Button>\n <Button\n type={!isMobile ? 'primary' : 'default'}\n onClick={() => setIsMobile(false)}\n >\n 桌面端\n </Button>\n </Space>\n }\n >\n <Card>\n <Descriptions title=\"移动端特性说明\" bordered column={1}>\n <Descriptions.Item label=\"当前模式\">\n {isMobile ? '移动端模式' : '桌面端模式'}\n </Descriptions.Item>\n <Descriptions.Item label=\"自动检测\">\n 当窗口宽度小于768px时自动切换为移动端模式\n </Descriptions.Item>\n <Descriptions.Item label=\"菜单展示\">\n {isMobile ? '左侧菜单隐藏,显示\"菜单\"按钮,点击后以Drawer形式展示' : '左侧固定菜单显示'}\n </Descriptions.Item>\n <Descriptions.Item label=\"默认收起\">\n Drawer默认关闭,点击按钮后打开\n </Descriptions.Item>\n <Descriptions.Item label=\"强制控制\">\n 可通过isMobile属性强制指定为移动端或桌面端模式\n </Descriptions.Item>\n <Descriptions.Item label=\"布局调整\">\n 移动端模式下内容区边距和圆角会自动调整\n </Descriptions.Item>\n </Descriptions>\n </Card>\n\n <Card title=\"示例数据\" style={{marginTop: 16}}>\n <Paragraph>\n 这是移动端适配的示例内容。在实际业务中,这里会显示具体的业务数据和操作界面。\n </Paragraph>\n <Space direction=\"vertical\" style={{width: '100%'}}>\n <Button block>操作按钮1</Button>\n <Button block>操作按钮2</Button>\n <Button block type=\"primary\">主要操作</Button>\n </Space>\n </Card>\n </Page>\n </Layout>\n );\n};\n\nrender(\n <PureGlobal>\n <MobileExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"layout\",\n packageName: \"@components/Layout\",\n component: component_65\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_67\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_66\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_69 from '@components/Menu';\nimport * as component_70 from 'antd';\nconst readmeConfig = {\n name: `Menu`,\n summary: `<p>Menu 是一个功能丰富的菜单导航组件,支持多级菜单、远程数据加载、权限控制和路径匹配。适用于各种侧边栏导航、顶部导航和下拉菜单场景。</p>`,\n \n \n api: `<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>allowCollapsed</td>\n<td>是否允许子菜单折叠</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>currentKey</td>\n<td>当前选中的菜单项key</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultCurrentKey</td>\n<td>默认选中的菜单项key</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultItems</td>\n<td>默认菜单项数组</td>\n<td>MenuItemProps[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultOpenKeys</td>\n<td>默认展开的菜单项key数组</td>\n<td>string[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items</td>\n<td>菜单项数组</td>\n<td>MenuItemProps[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>选中项改变时的回调函数</td>\n<td>(key: string) => void</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onItemsChange</td>\n<td>菜单项改变时的回调函数</td>\n<td>(items: MenuItemProps[]) => void</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onOpenChange</td>\n<td>展开项改变时的回调函数</td>\n<td>(openKeys: string[]) => void</td>\n<td>-</td>\n</tr>\n<tr>\n<td>openKeys</td>\n<td>当前展开的菜单项key数组</td>\n<td>string[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>pathMatch</td>\n<td>路径匹配函数</td>\n<td>(path: string, location: { pathname: string, search: string }) => boolean</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>MenuItemProps</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>children</td>\n<td>子菜单项</td>\n<td>MenuItemProps[]</td>\n<td>-</td>\n</tr>\n<tr>\n<td>fetchOptions</td>\n<td>远程加载子菜单的配置</td>\n<td>FetchOptions</td>\n<td>-</td>\n</tr>\n<tr>\n<td>icon</td>\n<td>菜单项图标React节点</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>iconType</td>\n<td>菜单项图标类型</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>label</td>\n<td>菜单项标签</td>\n<td>string</td>\n<td>ReactNode</td>\n</tr>\n<tr>\n<td>onClick</td>\n<td>点击菜单项的回调函数</td>\n<td>(key: string, props: MenuItemProps) => void</td>\n<td>-</td>\n</tr>\n<tr>\n<td>path</td>\n<td>菜单项对应的路径</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>request</td>\n<td>权限请求配置</td>\n<td>object</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>FetchOptions</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>loader</td>\n<td>数据加载函数</td>\n<td>() => Promise<MenuItemProps[]></td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础菜单`,\n description: `展示菜单的基本用法,包括多级菜单、无图标菜单、不可折叠菜单和单级菜单`,\n code: `const { default: Menu } = _Menu;\nconst { Space, Card, Typography } = antd;\nconst { useState } = React;\n\nconst { Title, Text } = Typography;\n\n// 基础多级菜单示例\nconst BaseMenuExample = () => {\n return (\n <Card title=\"基础多级菜单\" size=\"small\">\n <Menu\n defaultItems={[\n {\n label: \"用户管理\",\n iconType: \"icon-yonghuguanli\",\n children: [\n {\n label: \"用户列表\",\n path: \"/users\",\n },\n {\n label: \"角色管理\",\n path: \"/roles\",\n },\n ],\n },\n {\n label: \"系统设置\",\n iconType: \"icon-shezhi\",\n children: [\n {\n label: \"基础配置\",\n path: \"/settings/basic\",\n },\n {\n label: \"权限配置\",\n path: \"/settings/permissions\",\n },\n ],\n },\n {\n label: \"数据统计\",\n iconType: \"icon-tongji\",\n path: \"/statistics\",\n },\n ]}\n />\n </Card>\n );\n};\n\n// 无图标菜单示例\nconst NoIconMenuExample = () => {\n return (\n <Card title=\"无图标菜单\" size=\"small\">\n <Menu\n defaultItems={[\n {\n label: \"首页\",\n path: \"/home\",\n },\n {\n label: \"产品\",\n children: [\n {\n label: \"产品列表\",\n path: \"/products/list\",\n },\n {\n label: \"产品分类\",\n path: \"/products/categories\",\n },\n ],\n },\n {\n label: \"关于我们\",\n path: \"/about\",\n },\n ]}\n />\n </Card>\n );\n};\n\n// 不可折叠菜单示例\nconst NoCollapsedMenuExample = () => {\n return (\n <Card title=\"不可折叠菜单\" size=\"small\">\n <Menu\n allowCollapsed={false}\n defaultItems={[\n {\n label: \"订单管理\",\n iconType: \"icon-dingdanguanli\",\n children: [\n {\n label: \"所有订单\",\n path: \"/orders/all\",\n },\n {\n label: \"待处理\",\n path: \"/orders/pending\",\n },\n {\n label: \"已完成\",\n path: \"/orders/completed\",\n },\n ],\n },\n {\n label: \"客户管理\",\n iconType: \"icon-kehuguanli\",\n children: [\n {\n label: \"客户列表\",\n path: \"/customers/list\",\n },\n {\n label: \"客户分组\",\n path: \"/customers/groups\",\n },\n ],\n },\n ]}\n />\n </Card>\n );\n};\n\n// 单级菜单示例\nconst SingleLevelMenuExample = () => {\n return (\n <Card title=\"单级菜单\" size=\"small\">\n <Menu\n defaultItems={[\n {\n label: \"仪表盘\",\n iconType: \"icon-yibiaopan\",\n path: \"/dashboard\",\n },\n {\n label: \"文档\",\n iconType: \"icon-wendang\",\n path: \"/documents\",\n },\n {\n label: \"消息中心\",\n iconType: \"icon-xiaoxizhongxin\",\n path: \"/messages\",\n },\n {\n label: \"个人设置\",\n iconType: \"icon-gerenshezhi\",\n path: \"/profile\",\n },\n ]}\n />\n </Card>\n );\n};\n\n// 受控菜单示例\nconst ControlledMenuExample = () => {\n const [currentKey, setCurrentKey] = useState(\"products\");\n \n return (\n <Card title=\"受控菜单\" size=\"small\">\n <Text type=\"secondary\">当前选中项: {currentKey}</Text>\n <Menu\n currentKey={currentKey}\n onChange={setCurrentKey}\n items={[\n {\n label: \"产品\",\n key: \"products\",\n iconType: \"icon-chanpin\",\n path: \"/products\",\n },\n {\n label: \"订单\",\n key: \"orders\",\n iconType: \"icon-dingdan\",\n path: \"/orders\",\n },\n {\n label: \"客户\",\n key: \"customers\",\n iconType: \"icon-kehu\",\n path: \"/customers\",\n },\n {\n label: \"财务\",\n key: \"finance\",\n iconType: \"icon-caiwu\",\n path: \"/finance\",\n },\n ]}\n />\n </Card>\n );\n};\n\nconst BasicExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <BaseMenuExample />\n </div>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <NoIconMenuExample />\n </div>\n </div>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <NoCollapsedMenuExample />\n </div>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <SingleLevelMenuExample />\n </div>\n </div>\n <div style={{ minWidth: '240px', maxWidth: '480px' }}>\n <ControlledMenuExample />\n </div>\n </Space>\n );\n};\n\nrender(<BasicExample />);\n`,\n scope: [{\n name: \"_Menu\",\n packageName: \"@components/Menu\",\n component: component_69\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_70\n}]\n},{\n title: `远程数据加载`,\n description: `展示菜单的远程数据加载功能,包括嵌套远程加载和自定义加载状态`,\n code: `const { default: Menu } = _Menu;\nconst { Space, Card, Typography } = antd;\nconst { useState } = React;\n\nconst { Title, Text } = Typography;\n\n// 远程加载数据的菜单示例\nconst RemoteDataMenuExample = () => {\n return (\n <Card title=\"远程加载数据\" size=\"small\">\n <Text type=\"secondary\">点击\"动态部门\"菜单项,会异步加载子菜单数据</Text>\n <Menu\n defaultItems={[\n {\n label: \"静态菜单\",\n iconType: \"icon-jingtai\",\n children: [\n {\n label: \"子菜单项1\",\n path: \"/static/item1\",\n },\n {\n label: \"子菜单项2\",\n path: \"/static/item2\",\n },\n ],\n },\n {\n label: \"动态部门\",\n iconType: \"icon-bumen\",\n fetchOptions: {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"技术部\",\n path: \"/dept/tech\",\n },\n {\n label: \"产品部\",\n path: \"/dept/product\",\n },\n {\n label: \"市场部\",\n path: \"/dept/marketing\",\n },\n {\n label: \"人力资源部\",\n path: \"/dept/hr\",\n },\n ]);\n }, 1000);\n });\n },\n },\n },\n {\n label: \"动态项目\",\n iconType: \"icon-xiangmu\",\n fetchOptions: {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"进行中项目\",\n children: [\n {\n label: \"网站改版\",\n path: \"/projects/website\",\n },\n {\n label: \"APP开发\",\n path: \"/projects/app\",\n },\n ],\n },\n {\n label: \"已完成项目\",\n path: \"/projects/completed\",\n },\n ]);\n }, 1500);\n });\n },\n },\n },\n ]}\n />\n </Card>\n );\n};\n\n// 嵌套远程加载的菜单示例\nconst NestedRemoteMenuExample = () => {\n return (\n <Card title=\"嵌套远程加载\" size=\"small\">\n <Text type=\"secondary\">多级菜单可以嵌套远程加载,点击后逐级加载数据</Text>\n <Menu\n defaultItems={[\n {\n label: \"数据中心\",\n iconType: \"icon-shujuzhongxin\",\n fetchOptions: {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"数据报表\",\n fetchOptions: {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"日报表\",\n path: \"/data/daily\",\n },\n {\n label: \"周报表\",\n path: \"/data/weekly\",\n },\n {\n label: \"月报表\",\n path: \"/data/monthly\",\n },\n ]);\n }, 800);\n });\n },\n },\n },\n {\n label: \"数据源管理\",\n path: \"/data/sources\",\n },\n ]);\n }, 1000);\n });\n },\n },\n },\n ]}\n />\n </Card>\n );\n};\n\n// 自定义加载内容示例\nconst CustomLoadingMenuExample = () => {\n return (\n <Card title=\"自定义加载状态\" size=\"small\">\n <Text type=\"secondary\">可以通过fetchOptions配置自定义加载状态</Text>\n <Menu\n defaultItems={[\n {\n label: \"快速操作\",\n iconType: \"icon-kuaisucaozuo\",\n children: [\n {\n label: \"新建文档\",\n path: \"/quick/new-doc\",\n },\n {\n label: \"上传文件\",\n path: \"/quick/upload\",\n },\n ],\n },\n {\n label: \"云存储\",\n iconType: \"icon-yuncunchu\",\n fetchOptions: {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"我的文档\",\n path: \"/cloud/docs\",\n },\n {\n label: \"共享文档\",\n path: \"/cloud/shared\",\n },\n {\n label: \"回收站\",\n path: \"/cloud/trash\",\n },\n ]);\n }, 2000);\n });\n },\n },\n },\n ]}\n />\n </Card>\n );\n};\n\nconst RemoteDataExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <RemoteDataMenuExample />\n </div>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <NestedRemoteMenuExample />\n </div>\n </div>\n <div style={{ minWidth: '240px', maxWidth: '480px' }}>\n <CustomLoadingMenuExample />\n </div>\n </Space>\n );\n};\n\nrender(<RemoteDataExample />);\n`,\n scope: [{\n name: \"_Menu\",\n packageName: \"@components/Menu\",\n component: component_69\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_70\n}]\n},{\n title: `自定义交互`,\n description: `展示菜单的交互功能,包括菜单项点击、动态菜单控制和展开状态控制`,\n code: `const { default: Menu } = _Menu;\nconst { Space, Card, Typography, Button, message } = antd;\nconst { useState } = React;\n\nconst { Title, Text } = Typography;\n\n// 菜单项点击交互示例\nconst MenuInteractionExample = () => {\n const [currentKey, setCurrentKey] = useState(\"dashboard\");\n \n const handleMenuClick = (key, props) => {\n setCurrentKey(key);\n message.info(\\`点击了菜单项: \\${props.label}\\`);\n };\n \n return (\n <Card title=\"菜单项点击交互\" size=\"small\">\n <Text type=\"secondary\">点击菜单项触发自定义交互和消息提示</Text>\n <Menu\n currentKey={currentKey}\n onChange={setCurrentKey}\n items={[\n {\n label: \"仪表盘\",\n key: \"dashboard\",\n iconType: \"icon-yibiaopan\",\n onClick: handleMenuClick,\n },\n {\n label: \"用户管理\",\n key: \"users\",\n iconType: \"icon-yonghuguanli\",\n onClick: handleMenuClick,\n children: [\n {\n label: \"用户列表\",\n key: \"user-list\",\n onClick: handleMenuClick,\n },\n {\n label: \"角色管理\",\n key: \"roles\",\n onClick: handleMenuClick,\n },\n ],\n },\n {\n label: \"系统设置\",\n key: \"settings\",\n iconType: \"icon-shezhi\",\n onClick: handleMenuClick,\n children: [\n {\n label: \"基础配置\",\n key: \"basic-settings\",\n onClick: handleMenuClick,\n },\n {\n label: \"安全设置\",\n key: \"security-settings\",\n onClick: handleMenuClick,\n },\n ],\n },\n ]}\n />\n </Card>\n );\n};\n\n// 动态菜单控制示例\nconst DynamicMenuExample = () => {\n const [menuItems, setMenuItems] = useState([\n {\n label: \"任务管理\",\n iconType: \"icon-renwuguanli\",\n key: \"tasks\",\n children: [\n {\n label: \"我的任务\",\n key: \"my-tasks\",\n path: \"/tasks/my\",\n },\n {\n label: \"团队任务\",\n key: \"team-tasks\",\n path: \"/tasks/team\",\n },\n ],\n },\n {\n label: \"文档管理\",\n iconType: \"icon-wendangguanli\",\n key: \"docs\",\n path: \"/docs\",\n },\n ]);\n \n const addMenuItem = () => {\n const newItem = {\n label: \\`新菜单项 \\${menuItems.length + 1}\\`,\n iconType: \"icon-xinjian\",\n key: \\`new-\\${Date.now()}\\`,\n path: \\`/new/\\${menuItems.length}\\`,\n };\n setMenuItems([...menuItems, newItem]);\n message.success(\"已添加新菜单项\");\n };\n \n const removeLastMenuItem = () => {\n if (menuItems.length > 0) {\n setMenuItems(menuItems.slice(0, -1));\n message.success(\"已移除最后一个菜单项\");\n }\n };\n \n return (\n <Card title=\"动态菜单控制\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">通过代码动态添加和删除菜单项</Text>\n <Space>\n <Button type=\"primary\" size=\"small\" onClick={addMenuItem}>\n 添加菜单项\n </Button>\n <Button size=\"small\" onClick={removeLastMenuItem}>\n 移除最后一项\n </Button>\n </Space>\n <Menu\n items={menuItems}\n />\n </Space>\n </Card>\n );\n};\n\n// 展开状态控制示例\nconst ExpandControlExample = () => {\n const [openKeys, setOpenKeys] = useState([\"product\", \"orders\"]);\n \n const expandAll = () => {\n setOpenKeys([\"product\", \"orders\", \"users\", \"settings\"]);\n message.success(\"已展开所有菜单\");\n };\n \n const collapseAll = () => {\n setOpenKeys([]);\n message.success(\"已收起所有菜单\");\n };\n \n return (\n <Card title=\"展开状态控制\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Text type=\"secondary\">通过代码控制菜单的展开和收起状态</Text>\n <Space>\n <Button type=\"primary\" size=\"small\" onClick={expandAll}>\n 展开全部\n </Button>\n <Button size=\"small\" onClick={collapseAll}>\n 收起全部\n </Button>\n </Space>\n <Menu\n openKeys={openKeys}\n onOpenChange={setOpenKeys}\n defaultItems={[\n {\n label: \"产品管理\",\n key: \"product\",\n iconType: \"icon-chanpin\",\n children: [\n {\n label: \"产品列表\",\n path: \"/products/list\",\n },\n {\n label: \"产品分类\",\n path: \"/products/categories\",\n },\n ],\n },\n {\n label: \"订单管理\",\n key: \"orders\",\n iconType: \"icon-dingdan\",\n children: [\n {\n label: \"订单列表\",\n path: \"/orders/list\",\n },\n {\n label: \"订单统计\",\n path: \"/orders/stats\",\n },\n ],\n },\n {\n label: \"用户管理\",\n key: \"users\",\n iconType: \"icon-yonghuguanli\",\n children: [\n {\n label: \"用户列表\",\n path: \"/users/list\",\n },\n {\n label: \"权限设置\",\n path: \"/users/permissions\",\n },\n ],\n },\n {\n label: \"系统设置\",\n key: \"settings\",\n iconType: \"icon-shezhi\",\n children: [\n {\n label: \"基础设置\",\n path: \"/settings/basic\",\n },\n {\n label: \"安全设置\",\n path: \"/settings/security\",\n },\n ],\n },\n ]}\n />\n </Space>\n </Card>\n );\n};\n\nconst CustomInteractionExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <MenuInteractionExample />\n </div>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <DynamicMenuExample />\n </div>\n </div>\n <div style={{ minWidth: '240px', maxWidth: '480px' }}>\n <ExpandControlExample />\n </div>\n </Space>\n );\n};\n\nrender(<CustomInteractionExample />);\n`,\n scope: [{\n name: \"_Menu\",\n packageName: \"@components/Menu\",\n component: component_69\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_70\n}]\n},{\n title: `权限控制与路由匹配`,\n description: `展示菜单的权限控制和路由匹配功能,包括自定义路径匹配和嵌套路由`,\n code: `const { default: Menu } = _Menu;\nconst { Space, Card, Typography, Switch, Alert } = antd;\nconst { useState, useMemo } = React;\n\nconst { Title, Text } = Typography;\n\n// 权限控制菜单示例\nconst PermissionMenuExample = () => {\n const [hasAdminPermission, setHasAdminPermission] = useState(true);\n const [hasUserPermission, setUserPermission] = useState(true);\n \n const menuItems = useMemo(() => [\n {\n label: \"首页\",\n iconType: \"icon-shouye\",\n path: \"/home\",\n },\n {\n label: \"用户管理\",\n iconType: \"icon-yonghuguanli\",\n request: {\n permission: \"user:view\",\n },\n children: [\n {\n label: \"用户列表\",\n path: \"/users/list\",\n request: {\n permission: \"user:list\",\n },\n },\n {\n label: \"用户详情\",\n path: \"/users/detail\",\n request: {\n permission: \"user:detail\",\n },\n },\n {\n label: \"用户操作\",\n path: \"/users/actions\",\n request: {\n permission: [\"user:create\", \"user:edit\", \"user:delete\"],\n },\n },\n ],\n },\n {\n label: \"系统管理\",\n iconType: \"icon-xitongguanli\",\n request: {\n permission: [\"admin:view\", \"admin:full\"],\n },\n children: [\n {\n label: \"系统配置\",\n path: \"/system/config\",\n request: {\n permission: \"admin:config\",\n },\n },\n {\n label: \"权限管理\",\n path: \"/system/permission\",\n request: {\n permission: \"admin:permission\",\n },\n },\n ],\n },\n {\n label: \"数据统计\",\n iconType: \"icon-shujutongji\",\n path: \"/statistics\",\n },\n ], []);\n \n return (\n <Card title=\"权限控制菜单\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <Text>用户管理权限:</Text>\n <Switch checked={hasUserPermission} onChange={setUserPermission} />\n <Text>管理员权限:</Text>\n <Switch checked={hasAdminPermission} onChange={setHasAdminPermission} />\n </Space>\n <Alert\n message=\"权限说明\"\n description=\"根据用户权限控制菜单项的显示,无权限的菜单项将不会显示\"\n type=\"info\"\n showIcon\n />\n <Menu\n defaultItems={menuItems}\n />\n </Space>\n </Card>\n );\n};\n\n// 自定义路径匹配示例\nconst PathMatchExample = () => {\n const [matchType, setMatchType] = useState(\"exact\");\n \n const customPathMatch = (path, location) => {\n if (matchType === \"exact\") {\n // 精确匹配\n return location.pathname === path;\n } else if (matchType === \"startsWith\") {\n // 前缀匹配\n return location.pathname.startsWith(path);\n } else if (matchType === \"custom\") {\n // 自定义匹配逻辑 - 包含特定标识符\n return location.pathname.includes(path.split(\"/\").pop());\n }\n return false;\n };\n \n return (\n <Card title=\"自定义路径匹配\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <Text>匹配类型:</Text>\n <Switch \n checked={matchType === \"exact\"} \n onChange={(checked) => setMatchType(checked ? \"exact\" : \"startsWith\")}\n />精确匹配\n <Switch \n checked={matchType === \"custom\"} \n onChange={(checked) => setMatchType(checked ? \"custom\" : \"startsWith\")}\n />自定义匹配\n </Space>\n <Alert\n message=\"匹配说明\"\n description=\"精确匹配要求路径完全相同,前缀匹配要求路径以指定路径开头,自定义匹配使用特殊规则\"\n type=\"info\"\n showIcon\n />\n <Menu\n pathMatch={customPathMatch}\n defaultItems={[\n {\n label: \"用户管理\",\n iconType: \"icon-yonghuguanli\",\n path: \"/users\",\n children: [\n {\n label: \"用户列表\",\n path: \"/users/list\",\n },\n {\n label: \"用户详情\",\n path: \"/users/detail\",\n },\n ],\n },\n {\n label: \"产品管理\",\n iconType: \"icon-chanpin\",\n path: \"/products\",\n children: [\n {\n label: \"产品列表\",\n path: \"/products/list\",\n },\n {\n label: \"产品详情\",\n path: \"/products/detail\",\n },\n ],\n },\n ]}\n />\n </Space>\n </Card>\n );\n};\n\n// 嵌套路由匹配示例\nconst NestedRouteExample = () => {\n return (\n <Card title=\"嵌套路由匹配\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert\n message=\"嵌套路由说明\"\n description=\"当访问子菜单路径时,父菜单也会自动高亮显示\"\n type=\"info\"\n showIcon\n />\n <Menu\n defaultItems={[\n {\n label: \"用户中心\",\n iconType: \"icon-yonghuzhongxin\",\n path: \"/user\",\n children: [\n {\n label: \"基本信息\",\n path: \"/user/profile\",\n },\n {\n label: \"账户安全\",\n path: \"/user/security\",\n },\n {\n label: \"通知设置\",\n path: \"/user/notifications\",\n },\n ],\n },\n {\n label: \"项目管理\",\n iconType: \"icon-xiangmuguanli\",\n path: \"/project\",\n children: [\n {\n label: \"进行中项目\",\n path: \"/project/active\",\n },\n {\n label: \"已完成项目\",\n path: \"/project/completed\",\n },\n {\n label: \"项目详情\",\n path: \"/project/detail\",\n },\n ],\n },\n ]}\n />\n </Space>\n </Card>\n );\n};\n\nconst PermissionRoutingExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <PermissionMenuExample />\n </div>\n <div style={{ minWidth: '240px', flex: 1 }}>\n <PathMatchExample />\n </div>\n </div>\n <div style={{ minWidth: '240px', maxWidth: '480px' }}>\n <NestedRouteExample />\n </div>\n </Space>\n );\n};\n\nrender(<PermissionRoutingExample />);\n`,\n scope: [{\n name: \"_Menu\",\n packageName: \"@components/Menu\",\n component: component_69\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_70\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_89 from '@components/Modal';\nimport * as component_90 from '@components/FormInfo';\nimport * as component_91 from 'antd';\nimport * as component_92 from '@components/Global';\nimport * as component_93 from '@kne/react-fetch';\nimport * as component_94 from '@components/Content';\nconst readmeConfig = {\n name: `Modal`,\n summary: `<h3>概述</h3>\n<p>Modal 是一个基于 Ant Design Modal 组件的增强型弹窗组件,提供了更丰富的功能和更简洁的API。支持多种弹窗形式,适用于需要弹窗交互的各种场景。</p>\n<h3>何时使用</h3>\n<p>需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以在当前页面正中打开一个浮层,承载相应的操作。</p>\n<h3>特点</h3>\n<p>该组件是antd Modal组件的再封装:</p>\n<ul>\n<li>修改了footer部分的设置逻辑,能更加简单的定义footer区域的功能</li>\n<li>添加了withDecorator可以更加方便的处理Modal外层的显示逻辑</li>\n<li>扩展了用于方法调用的useModal的hooks,可以通过hooks获得一个Modal的调用方法,并且保证其和Modal组件式调用有相同的UI表现和行为</li>\n<li>扩展了ModalButton组件,可以在点击该按钮时执行加载数据,并且Button的状态变为loading,在数据加载完成之后再弹出弹窗</li>\n<li>扩展了TabsModal组件,它是一个Tabs和Modal组合起来的组件,对弹窗title做了特殊处理,更加符合UI交互逻辑</li>\n</ul>\n<h3>组件构成</h3>\n<p>Modal 组件家族包含以下组件:</p>\n<ul>\n<li><strong>Modal</strong>: 基础弹窗组件</li>\n<li><strong>useModal</strong>: Hook,用于命令式调用弹窗</li>\n<li><strong>TabsModal</strong>: 带选项卡的弹窗组件</li>\n<li><strong>useTabsModal</strong>: Hook,用于命令式调用选项卡弹窗</li>\n<li><strong>ModalButton</strong>: 可加载数据的弹窗按钮</li>\n<li><strong>TabsModalButton</strong>: 可加载数据的选项卡弹窗按钮</li>\n</ul>`,\n \n \n api: `<h2>Modal</h2>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>footer</td>\n<td>弹窗的footer,当其被显式设置成null且footerButtons没有设置过时弹窗不显示footer。当它类型为function时可以得到close方法和withDecorator设置的 props</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>footerButtons</td>\n<td>弹窗footer的按钮区,默认为确认和取消按钮,默认按钮分别响应onConfirm和onCancel方法,如果自定义设置footerButtons则需要自行传入onClick参数,onConfirm和onCancel方法将不生效</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onClose</td>\n<td>弹窗关闭时调用,弹窗受控时由该方法将外部open状态修改</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onConfirm</td>\n<td>当footerButtons未自定义设置时点击确认按钮触发执行该方法,当其返回Promise点击后Promise,resolve之前确认按钮显示为loading状态,返回值为false或者Promise的resolve值为false时弹窗不会被关闭,其他情况弹窗默认关闭</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onCancel</td>\n<td>和onConfirm类似,其为点击取消按钮触发</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>children</td>\n<td>弹窗内容,可以为jsx或者function,为function时可以接收到close和withDecorator设置的 props</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>弹窗修饰器,会接收到弹窗children的render方法,可以在其外部添加修饰内容后执行render方法,给render方法传入的值可以在children,footer,rightOptions类型为function时接收到对应的参数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rightOptions</td>\n<td>弹窗右侧区域,和children类似可以为jsx或者function类型</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>maskClosable</td>\n<td>点击蒙层是否允许关闭</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数参考antd Modal组件</p>\n<h3>useModal</h3>\n<p>获取一个执行后可以弹出一个Modal组件的方法</p>\n<h4>返回值:modal</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>modal</td>\n<td>执行后可以弹出一个Modal弹窗,参数同Modal组件参数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>TabsModal</h3>\n<p>一个Tabs和Modal组合起来的组件,对弹窗title做了特殊处理,更加符合UI交互逻辑</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>items</td>\n<td>同antd Tabs的items参数</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].label</td>\n<td>选项卡头显示文字</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].children</td>\n<td>选项卡头显示内容,和antd Tabs不同的是它可以是一个function和Modal的children类似可以接收items[].withDecorator传入的参数</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].key</td>\n<td>对应activeKey值</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].withDecorator</td>\n<td>弹窗修饰器和Modal的withDecorator作用一致</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>activeKey</td>\n<td>当前激活 tab 面板的 key</td>\n<td>string</td>\n<td></td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>弹窗修饰器和Modal的withDecorator作用一致</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultActiveKey</td>\n<td>初始化选中面板的 key,如果没有设置 activeKey</td>\n<td>string</td>\n<td></td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>切换面板的回调</td>\n<td>function</td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<h3>useTabsModal</h3>\n<p>获取一个执行后可以弹出一个TabsModal组件的方法</p>\n<h4>返回值:tabsModal</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>tabsModal</td>\n<td>执行后可以弹出一个TabsModal弹窗,参数同TabsModal组件参数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>ModalButton</h3>\n<p>点击以后可以执行获取数据,在数据未返回时按钮展示为loading状态,数据返回后弹出Modal弹窗</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>@kne/react-fetch 所需参数</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>同Modal参数,当它为function时,执行function后返回的值作为modalProps</td>\n<td>object,function({data,fetchApi,close})</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数同antd Button 组件</p>\n<h3>TabsModalButton</h3>\n<p>点击以后可以执行获取数据,在数据未返回时按钮展示为loading状态,数据返回后弹出TabsModal弹窗</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>@kne/react-fetch 所需参数</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>同TabsModal参数,当它为function时,执行function后返回的值作为modalProps</td>\n<td>object,function({data,fetchApi,close})</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数同antd Button 组件</p>\n<h3>useModal</h3>\n<p>获取一个执行后可以弹出一个Modal组件的方法</p>\n<h4>return:modal</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>modal</td>\n<td>执行后可以弹出一个Modal弹窗,参数同Modal组件参数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>TabsModal</h3>\n<p>一个Tabs和Modal组合起来的组件,对弹窗title做了特殊处理,更加符合UI交互逻辑</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>items</td>\n<td>同antd Tabs的items参数</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].label</td>\n<td>选项卡头显示文字</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].children</td>\n<td>选项卡头显示内容,和antd Tabs不同的是它可以是一个function和Modal的children类似可以接收items[].withDecorator传入的参数</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>items[].key</td>\n<td>对应activeKey值</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>activeKey</td>\n<td>当前激活 tab 面板的 key</td>\n<td>string</td>\n<td></td>\n</tr>\n<tr>\n<td>withDecorator</td>\n<td>弹窗修饰器和Modal的withDecorator作用一致</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultActiveKey</td>\n<td>初始化选中面板的 key,如果没有设置 activeKey</td>\n<td>string</td>\n<td></td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>切换面板的回调</td>\n<td>function</td>\n<td></td>\n</tr>\n</tbody>\n</table>\n<h3>useTabsModal</h3>\n<p>获取一个执行后可以弹出一个TabsModal组件的方法</p>\n<h4>return:tabsModal</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>tabsModal</td>\n<td>执行后可以弹出一个TabsModal弹窗,参数同TabsModal组件参数</td>\n<td>function</td>\n</tr>\n</tbody>\n</table>\n<h3>ModalButton</h3>\n<p>点击以后可以执行获取数据,在数据未返回时按钮展示为loading状态,数据返回后弹出Modal弹窗</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>@kne/react-fetch 所需参数</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>同Modal参数,当它为function时,执行function后返回的值作为modalProps</td>\n<td>object,function({data,fetchApi,close})</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数同antd Button 组件</p>\n<h3>TabsModalButton</h3>\n<p>点击以后可以执行获取数据,在数据未返回时按钮展示为loading状态,数据返回后弹出TabsModal弹窗</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>@kne/react-fetch 所需参数</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>modalProps</td>\n<td>同TabsModal参数,当它为function时,执行function后返回的值作为modalProps</td>\n<td>object,function({data,fetchApi,close})</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数同antd Button 组件</p>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础弹窗`,\n description: `展示Modal组件的基本用法,包括不同尺寸、异步确认、自定义按钮和命令式调用等`,\n code: `const { default: Modal, useModal } = _Modal;\nconst { default: FormInfo, useFormModal, fields } = _FormInfo;\nconst { useState } = React;\nconst { Button, Space, message, Radio, Input } = antd;\n\n// 基础弹窗示例\nconst BasicModalExample = () => {\n const [open, setOpen] = useState(false);\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开基础弹窗\n </Button>\n \n <Modal\n title=\"基础弹窗\"\n open={open}\n onClose={() => setOpen(false)}\n onConfirm={() => {\n message.success(\"操作成功\");\n setOpen(false);\n }}\n >\n <p>这是一个基础弹窗的内容</p>\n <p>弹窗支持确认和取消操作</p>\n </Modal>\n </Space>\n );\n};\n\n// 不同尺寸的弹窗示例\nconst SizeModalExample = () => {\n const [open, setOpen] = useState(false);\n const [size, setSize] = useState(\"default\");\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Radio.Group\n value={size}\n options={[\n { label: \"小号\", value: \"small\" },\n { label: \"默认\", value: \"default\" },\n { label: \"大号\", value: \"large\" },\n ]}\n onChange={(e) => setSize(e.target.value)}\n />\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开{size === \"small\" ? \"小号\" : size === \"large\" ? \"大号\" : \"默认\"}弹窗\n </Button>\n \n <Modal\n title={\\`\\${size === \"small\" ? \"小号\" : size === \"large\" ? \"大号\" : \"默认\"}尺寸弹窗\\`}\n size={size}\n open={open}\n onClose={() => setOpen(false)}\n onConfirm={() => setOpen(false)}\n >\n <p>这是一个{size}尺寸的弹窗</p>\n {size === \"large\" && (\n <div>\n <p>大号弹窗可以容纳更多内容</p>\n <p>适合展示复杂的表单或数据</p>\n <p>可以根据实际需求选择合适的尺寸</p>\n <p>内容会根据弹窗大小自动调整布局</p>\n </div>\n )}\n </Modal>\n </Space>\n );\n};\n\n// 异步确认的弹窗示例\nconst AsyncModalExample = () => {\n const [open, setOpen] = useState(false);\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开异步确认弹窗\n </Button>\n \n <Modal\n title=\"异步确认弹窗\"\n open={open}\n onClose={() => setOpen(false)}\n onConfirm={() => {\n return new Promise((resolve) => {\n message.loading(\"正在处理,请稍候...\", 0);\n setTimeout(() => {\n message.destroy();\n message.success(\"处理成功!\");\n resolve();\n }, 2000);\n });\n }}\n >\n <p>点击确认按钮后,将执行异步操作</p>\n <p>在操作完成前,确认按钮将显示为加载状态</p>\n <p>操作完成后,弹窗将自动关闭</p>\n </Modal>\n </Space>\n );\n};\n\n// 自定义按钮的弹窗示例\nconst CustomButtonModalExample = () => {\n const [open, setOpen] = useState(false);\n \n const handleSave = () => {\n return new Promise((resolve) => {\n message.loading(\"正在保存...\", 0);\n setTimeout(() => {\n message.destroy();\n message.success(\"保存成功!\");\n resolve();\n }, 1500);\n });\n };\n \n const handleCancel = () => {\n message.info(\"已取消操作\");\n setOpen(false);\n };\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开自定义按钮弹窗\n </Button>\n \n <Modal\n title=\"自定义按钮弹窗\"\n open={open}\n onClose={() => setOpen(false)}\n footerButtons={[\n {\n children: \"取消\",\n onClick: handleCancel,\n },\n {\n children: \"保存\",\n type: \"primary\",\n onClick: handleSave,\n },\n {\n children: \"保存并新建\",\n onClick: () => {\n handleSave().then(() => {\n message.info(\"可以继续添加新内容\");\n });\n },\n },\n ]}\n >\n <p>这个弹窗有自定义的底部按钮</p>\n <p>每个按钮都可以有自己的点击处理逻辑</p>\n </Modal>\n </Space>\n );\n};\n\n// 命令式调用的弹窗示例\nconst CommandModalExample = () => {\n const modal = useModal();\n \n const openModal = () => {\n modal({\n title: \"命令式弹窗\",\n children: <div>\n <p>这是通过 useModal Hook 命令式打开的弹窗</p>\n <p>无需管理弹窗的显示状态</p>\n <p>适合在事件处理中直接使用</p>\n </div>,\n onConfirm: () => {\n message.success(\"确认操作\");\n },\n });\n };\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={openModal}>\n 打开命令式弹窗\n </Button>\n </Space>\n );\n};\n\n// 表单弹窗示例\nconst FormModalExample = () => {\n const formModal = useFormModal();\n \n const handleOpenForm = () => {\n formModal({\n title: \"用户信息表单\",\n formProps: {\n onSubmit: (data) => {\n console.log(\"表单值:\", data);\n message.success(\"保存成功\");\n },\n },\n children: (\n <FormInfo\n list={[\n <fields.Input name=\"name\" label=\"姓名\" rule=\"REQ\" />,\n <fields.Input name=\"email\" label=\"邮箱\" rule=\"EMAIL\" />,\n <fields.TextArea name=\"remark\" label=\"备注\" />,\n ]}\n />\n ),\n });\n };\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={handleOpenForm}>\n 打开表单弹窗\n </Button>\n </Space>\n );\n};\n\nconst BasicModalExamples = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }} size=\"large\">\n <BasicModalExample />\n <SizeModalExample />\n <AsyncModalExample />\n <CustomButtonModalExample />\n <CommandModalExample />\n <FormModalExample />\n </Space>\n );\n};\n\nrender(<BasicModalExamples />);\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_90\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n}]\n},{\n title: `高级功能`,\n description: `展示Modal组件的高级功能,包括withDecorator装饰器、rightOptions右侧选项和高级命令式调用`,\n code: `const { default: Modal, useModal, TabsModal, useTabsModal, ModalButton, TabsModalButton } = _Modal;\nconst { default: FormInfo, fields } = _FormInfo;\nconst { useState, useCallback, useRef } = React;\nconst { Button, Space, message, Table, Input, Tabs, Badge, Switch, Avatar, Descriptions, List, Timeline, Tag, Divider } = antd;\n\n// 使用 withDecorator 的弹窗示例\nconst WithDecoratorModalExample = () => {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开带装饰器的弹窗\n </Button>\n \n <Modal\n title=\"带装饰器的弹窗\"\n open={open}\n onClose={() => setOpen(false)}\n withDecorator={(render) => {\n return (\n <div>\n <div style={{ background: '#f0f2f5', padding: '16px', marginBottom: '16px' }}>\n <p>这是通过 withDecorator 添加的外部装饰内容</p>\n <Space>\n <Button size=\"small\" onClick={() => setLoading(!loading)}>\n {loading ? '停止' : '开始'}加载\n </Button>\n <Badge status={loading ? 'processing' : 'default'} text={loading ? '加载中' : '空闲'} />\n </Space>\n </div>\n {loading ? (\n <div style={{ textAlign: 'center', padding: '20px' }}>\n 加载中,请稍候...\n </div>\n ) : (\n render({\n decoratorData: { loading, message: \"装饰器传递的数据\" }\n })\n )}\n </div>\n );\n }}\n onConfirm={() => {\n message.success(\"操作成功\");\n setOpen(false);\n }}\n >\n {({ decoratorData }) => (\n <div>\n <p>这是弹窗的主体内容</p>\n <p>从装饰器接收的数据: {JSON.stringify(decoratorData)}</p>\n </div>\n )}\n </Modal>\n </Space>\n );\n};\n\n// 使用 rightOptions 的弹窗示例\nconst RightOptionsModalExample = () => {\n const [open, setOpen] = useState(false);\n const [info, setInfo] = useState({ views: 0, likes: 0 });\n \n const rightOptions = (\n <div style={{ padding: '8px 16px', background: '#f5f5f5' }}>\n <Space direction=\"vertical\" size=\"small\">\n <div>浏览量: {info.views}</div>\n <div>点赞数: {info.likes}</div>\n <Button size=\"small\" type=\"primary\" onClick={() => {\n setInfo({ views: info.views + 1, likes: info.likes + 1 });\n }}>\n 更新数据\n </Button>\n </Space>\n </div>\n );\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开带右侧选项的弹窗\n </Button>\n \n <Modal\n title=\"带右侧选项的弹窗\"\n open={open}\n onClose={() => setOpen(false)}\n rightOptions={rightOptions}\n onConfirm={() => {\n message.success(\"操作成功\");\n setOpen(false);\n }}\n >\n <p>这是弹窗的主体内容</p>\n <p>右侧区域显示了额外的信息</p>\n <p>右侧区域通常用于显示辅助信息或操作</p>\n </Modal>\n </Space>\n );\n};\n\n// 命令式调用的高级弹窗示例\nconst AdvancedCommandModalExample = () => {\n const modal = useModal();\n const [data, setData] = useState(null);\n const modalApiRef = useRef(null);\n \n const openDataModal = useCallback(() => {\n const api = modal({\n title: \"数据详情弹窗\",\n width: 600,\n withDecorator: (render) => {\n return (\n <div>\n <Button \n style={{ marginBottom: 16 }} \n onClick={() => {\n setData([\n { key: '1', name: '张三', age: 28, address: '北京市朝阳区' },\n { key: '2', name: '李四', age: 32, address: '北京市海淀区' },\n ]);\n }}\n >\n 加载数据\n </Button>\n {render()}\n </div>\n );\n },\n children: () => (\n <div>\n {data ? (\n <Table\n dataSource={data}\n columns={[\n { title: '姓名', dataIndex: 'name', key: 'name' },\n { title: '年龄', dataIndex: 'age', key: 'age' },\n { title: '地址', dataIndex: 'address', key: 'address' },\n ]}\n pagination={false}\n />\n ) : (\n <div style={{ textAlign: 'center', padding: '40px' }}>\n 暂无数据,请点击\"加载数据\"按钮\n </div>\n )}\n </div>\n ),\n footerButtons: [\n {\n children: '刷新',\n onClick: () => {\n if (data) {\n setData([...data]);\n message.success(\"数据已刷新\");\n }\n },\n },\n {\n children: '关闭',\n onClick: () => {\n message.info(\"已关闭\");\n },\n },\n ],\n });\n modalApiRef.current = api;\n }, [modal, data]);\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={openDataModal}>\n 打开数据详情弹窗\n </Button>\n </Space>\n );\n};\n\n// TabsModal 示例\nconst TabsModalExample = () => {\n const [open, setOpen] = useState(false);\n const [loading, setLoading] = useState(false);\n const [activeTab, setActiveTab] = useState('basic');\n \n // 模拟数据\n const userData = {\n name: '张三',\n email: 'zhangsan@example.com',\n avatar: 'https://randomuser.me/api/portraits/men/1.jpg',\n department: '技术部',\n joinDate: '2020-05-15',\n projects: ['项目A', '项目B', '项目C'],\n skills: ['JavaScript', 'React', 'Node.js'],\n achievements: ['优秀员工', '技术创新奖', '团队协作奖'],\n };\n \n const items = [\n {\n key: 'basic',\n label: '基本信息',\n withDecorator: (render) => {\n return (\n <div>\n <p style={{ marginBottom: 16 }}>这是基本信息标签的装饰内容</p>\n {render()}\n </div>\n );\n },\n children: () => (\n <div style={{ padding: '16px 0' }}>\n <Space direction=\"vertical\" size=\"large\" style={{ width: '100%' }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>\n <Avatar size={64} src={userData.avatar} />\n <div>\n <h3>{userData.name}</h3>\n <p>{userData.email}</p>\n </div>\n </div>\n <Descriptions bordered column={1}>\n <Descriptions.Item label=\"部门\">{userData.department}</Descriptions.Item>\n <Descriptions.Item label=\"入职日期\">{userData.joinDate}</Descriptions.Item>\n </Descriptions>\n </Space>\n </div>\n ),\n },\n {\n key: 'projects',\n label: '项目经验',\n children: () => (\n <div style={{ padding: '16px 0' }}>\n <List\n header={<div>参与项目</div>}\n bordered\n dataSource={userData.projects}\n renderItem={(item, index) => (\n <List.Item>\n <List.Item.Meta\n avatar={<Avatar style={{ backgroundColor: '#1890ff' }}>{index + 1}</Avatar>}\n title={item}\n description={\\`这是\\${item}的描述信息,展示了项目的主要内容和成果。\\`}\n />\n </List.Item>\n )}\n />\n </div>\n ),\n },\n {\n key: 'skills',\n label: '技能特长',\n children: () => (\n <div style={{ padding: '16px 0' }}>\n <Space wrap>\n {userData.skills.map((skill, index) => (\n <Tag key={index} color=\"blue\" style={{ fontSize: '14px', padding: '4px 12px' }}>\n {skill}\n </Tag>\n ))}\n </Space>\n <Divider />\n <p>技能掌握程度评估:</p>\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n {userData.skills.map((skill, index) => (\n <div key={index} style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <div style={{ width: 80 }}>{skill}:</div>\n <div style={{ flex: 1, backgroundColor: '#f0f0f0', borderRadius: 4, height: 8, position: 'relative' }}>\n <div \n style={{ \n position: 'absolute', \n left: 0, \n top: 0, \n height: '100%', \n backgroundColor: '#1890ff',\n borderRadius: 4,\n width: \\`\\${80 - index * 10}%\\`\n }} \n />\n </div>\n <span>{90 - index * 10}%</span>\n </div>\n ))}\n </Space>\n </div>\n ),\n },\n {\n key: 'achievements',\n label: '成就荣誉',\n children: () => (\n <div style={{ padding: '16px 0' }}>\n <Timeline>\n {userData.achievements.map((achievement, index) => (\n <Timeline.Item \n key={index} \n color={index === 0 ? 'green' : index === 1 ? 'blue' : 'red'}\n >\n <p style={{ fontWeight: 'bold', marginBottom: 4 }}>{achievement}</p>\n <p style={{ color: '#666', fontSize: '12px' }}>\n {index === 0 ? '2023年度评选' : index === 1 ? '2022年度评选' : '2021年度评选'}\n </p>\n </Timeline.Item>\n ))}\n </Timeline>\n </div>\n ),\n },\n ];\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Button type=\"primary\" onClick={() => setOpen(true)}>\n 打开选项卡弹窗\n </Button>\n \n <TabsModal\n open={open}\n onClose={() => setOpen(false)}\n activeKey={activeTab}\n onChange={setActiveTab}\n items={items}\n onConfirm={() => {\n return new Promise((resolve) => {\n setLoading(true);\n setTimeout(() => {\n setLoading(false);\n message.success(\"操作成功\");\n resolve();\n }, 1500);\n });\n }}\n />\n </Space>\n );\n};\n\n// ModalButton 示例\nconst ModalButtonExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <p>ModalButton 可以在点击后加载数据,然后弹出弹窗</p>\n \n <ModalButton\n type=\"primary\"\n api={{\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n userInfo: {\n name: '张三',\n email: 'zhangsan@example.com',\n department: '技术部',\n position: '高级工程师',\n joinDate: '2020-05-15',\n }\n });\n }, 1500);\n });\n },\n }}\n modalProps={({ data }) => ({\n title: \"用户详情\",\n children: (\n <div>\n {data && data.userInfo ? (\n <>\n <p><strong>姓名:</strong> {data.userInfo.name || '未知'}</p>\n <p><strong>邮箱:</strong> {data.userInfo.email || '未知'}</p>\n <p><strong>部门:</strong> {data.userInfo.department || '未知'}</p>\n <p><strong>职位:</strong> {data.userInfo.position || '未知'}</p>\n <p><strong>入职日期:</strong> {data.userInfo.joinDate || '未知'}</p>\n </>\n ) : (\n <div style={{ textAlign: 'center', padding: '20px' }}>\n <p>加载用户信息失败</p>\n </div>\n )}\n </div>\n ),\n })}\n >\n 查看用户详情\n </ModalButton>\n \n <ModalButton\n api={{\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n { key: '1', name: '张三', age: 28, department: '技术部' },\n { key: '2', name: '李四', age: 32, department: '产品部' },\n { key: '3', name: '王五', age: 26, department: '设计部' },\n ]);\n }, 1000);\n });\n },\n }}\n modalProps={({ data }) => ({\n title: \"员工列表\",\n children: (\n <>\n {data && Array.isArray(data) && data.length > 0 ? (\n <Table\n dataSource={data}\n columns={[\n { title: '姓名', dataIndex: 'name', key: 'name' },\n { title: '年龄', dataIndex: 'age', key: 'age' },\n { title: '部门', dataIndex: 'department', key: 'department' },\n ]}\n pagination={false}\n />\n ) : (\n <div style={{ textAlign: 'center', padding: '20px' }}>\n <p>加载员工列表失败</p>\n </div>\n )}\n </>\n ),\n })}\n >\n 查看员工列表\n </ModalButton>\n </Space>\n );\n};\n\n// TabsModalButton 示例\nconst TabsModalButtonExample = () => {\n const formRef1 = useRef(null);\n const formRef2 = useRef(null);\n \n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <p>TabsModalButton 结合了 TabsModal 和数据加载功能</p>\n \n <TabsModalButton\n type=\"primary\"\n api={{\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n profile: {\n name: '李四',\n email: 'lisi@example.com',\n phone: '13800138000',\n },\n settings: {\n theme: 'dark',\n language: 'zh-CN',\n notifications: true,\n },\n });\n }, 1500);\n });\n },\n }}\n modalProps={({ data }) => ({\n title: \"用户设置\",\n items: [\n {\n key: 'profile',\n label: '个人信息',\n children: () => (\n <FormInfo \n ref={formRef1}\n data={data.profile}\n list={[\n <fields.Input name=\"name\" label=\"姓名\" />,\n <fields.Input name=\"email\" label=\"邮箱\" />,\n <fields.Input name=\"phone\" label=\"电话\" />,\n ]}\n />\n ),\n },\n {\n key: 'settings',\n label: '系统设置',\n children: () => (\n <FormInfo \n ref={formRef2}\n data={data.settings}\n list={[\n <fields.Input name=\"theme\" label=\"主题\" />,\n <fields.Input name=\"language\" label=\"语言\" />,\n <fields.Switch name=\"notifications\" label=\"通知\" />,\n ]}\n />\n ),\n },\n ],\n onConfirm: async () => {\n try {\n // 获取表单数据\n const form1Data = formRef1.current ? await formRef1.current.getData() : {};\n const form2Data = formRef2.current ? await formRef2.current.getData() : {};\n \n console.log('表单数据:', { ...form1Data, ...form2Data });\n return Promise.resolve();\n } catch (error) {\n console.error('表单验证失败:', error);\n throw error;\n }\n },\n })}\n >\n 打开用户设置\n </TabsModalButton>\n </Space>\n );\n};\n\nconst AdvancedModalExamples = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }} size=\"large\">\n <WithDecoratorModalExample />\n <RightOptionsModalExample />\n <AdvancedCommandModalExample />\n <TabsModalExample />\n <ModalButtonExample />\n <TabsModalButtonExample />\n </Space>\n );\n};\n\nrender(<AdvancedModalExamples />);\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_90\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n}]\n},{\n title: `FormModal表单弹窗`,\n description: `展示FormModal组件的用法,在弹窗中展示表单,适合数据录入、编辑等场景`,\n code: `const { FormModal, useFormModal } = _FormInfo;\nconst { Space, Button } = antd;\nconst { PureGlobal } = global;\nconst { default: FormInfo, List, Input, TextArea } = _FormInfo;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [open, setOpen] = useState(false);\n const formModal = useFormModal();\n return (\n <Space wrap>\n <FormModal\n open={open}\n title=\"表单弹窗\"\n onClose={() => {\n setOpen(false);\n }}\n formProps={{\n data: {\n productName: \"示例产品\",\n },\n onSubmit: async (data) => {\n console.log(data);\n await new Promise((resolve) => {\n setTimeout(() => {\n resolve();\n }, 1000);\n });\n setOpen(false);\n },\n }}\n >\n <FormInfo\n title=\"基本信息\"\n list={[\n <Input name=\"productName\" label=\"产品名称\" rule=\"REQ LEN-0-50\" />,\n <Input name=\"productCode\" label=\"产品编码\" rule=\"REQ LEN-0-20\" />,\n <TextArea name=\"description\" label=\"产品描述\" />,\n ]}\n />\n <List\n title=\"规格列表\"\n name=\"specifications\"\n maxLength={3}\n list={[\n <Input name=\"specName\" label=\"规格名称\" rule=\"REQ LEN-0-20\" />,\n <Input name=\"specValue\" label=\"规格值\" rule=\"REQ LEN-0-20\" />,\n <TextArea name=\"specRemark\" label=\"备注\" />,\n ]}\n />\n </FormModal>\n <Button\n onClick={() => {\n setOpen(true);\n }}\n >\n 组件调用\n </Button>\n <Button\n onClick={() => {\n const api = formModal({\n title: \"员工信息表单\",\n formProps: {\n data: {\n employeeName: \"张三\",\n },\n onSubmit: async (data) => {\n console.log(data);\n await new Promise((resolve) => {\n setTimeout(() => {\n resolve();\n }, 1000);\n });\n api.close();\n },\n },\n children: (\n <div>\n <FormInfo\n title=\"基本信息\"\n list={[\n <Input name=\"employeeName\" label=\"员工姓名\" rule=\"REQ LEN-0-20\" />,\n <Input name=\"employeeEmail\" label=\"邮箱\" rule=\"EMAIL\" />,\n <TextArea name=\"workExperience\" label=\"工作经历\" />,\n ]}\n />\n <List\n title=\"教育背景\"\n name=\"education\"\n maxLength={3}\n list={[\n <Input name=\"schoolName\" label=\"学校名称\" rule=\"REQ LEN-0-30\" />,\n <Input name=\"major\" label=\"专业\" rule=\"REQ LEN-0-20\" />,\n <TextArea name=\"degree\" label=\"学历学位\" />,\n ]}\n />\n </div>\n ),\n });\n }}\n >\n hooks调用\n </Button>\n <Button\n onClick={() => {\n const api = formModal({\n title: \"表单弹窗\",\n footerButtons: [\n { buttonType: \"CancelButton\", children: \"取消\" },\n {\n buttonType: \"FormApiButton\",\n autoClose: false,\n onClick: (context) => {\n console.log(context);\n },\n children: \"FormApiButton\",\n },\n {\n buttonType: \"SubmitButton\",\n autoClose: false,\n children: \"提交\",\n },\n ],\n formProps: {\n data: {\n projectName: \"新项目\",\n },\n onSubmit: async (data) => {\n console.log(data);\n await new Promise((resolve) => {\n setTimeout(() => {\n resolve();\n }, 1000);\n });\n api.close();\n },\n },\n children: (\n <div>\n <FormInfo\n title=\"项目信息\"\n list={[\n <Input name=\"projectName\" label=\"项目名称\" rule=\"REQ LEN-0-30\" />,\n <Input name=\"projectManager\" label=\"项目经理\" rule=\"REQ LEN-0-20\" />,\n <TextArea name=\"projectDescription\" label=\"项目描述\" />,\n ]}\n />\n <List\n title=\"项目成员\"\n name=\"members\"\n maxLength={3}\n list={[\n <Input name=\"memberName\" label=\"成员姓名\" rule=\"REQ LEN-0-20\" />,\n <Input name=\"memberRole\" label=\"成员角色\" rule=\"REQ LEN-0-20\" />,\n <TextArea name=\"memberRemark\" label=\"备注\" />,\n ]}\n />\n </div>\n ),\n });\n }}\n >\n 自定义footerButtons\n </Button>\n </Space>\n );\n};\n\nrender(\n <PureGlobal>\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_90\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_92\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n}]\n},{\n title: `TabsModal选项卡弹窗`,\n description: `展示TabsModal组件的用法,包括选项卡内容和装饰器功能`,\n code: `const { TabsModal, useTabsModal } = _Modal;\nconst { useState } = React;\nconst { default: Fetch } = fetch;\nconst { Button, Space } = antd;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst BaseExample = () => {\n const [open, setOpen] = useState(false);\n const tabsModal = useTabsModal();\n return <Space wrap>\n <TabsModal open={open} onClose={() => {\n setOpen(false);\n }} items={[{\n label: \"项目概述\", key: \"overview\", children: <div>项目基本信息、目标、时间计划和关键里程碑,帮助团队了解项目全貌</div>\n }, {\n label: \"任务分配\", key: \"tasks\", children: <div>项目任务分解、责任人分配、进度跟踪和优先级管理,确保项目按计划推进</div>\n }]} rightOptions={<div>快速操作面板:常用功能的快捷入口,提高操作效率</div>}>\n <div>选项卡弹窗主内容区域:展示多标签页的详细信息,支持在不同标签间切换查看</div>\n </TabsModal>\n <Button onClick={() => {\n setOpen(true);\n }}>组件调用方式</Button>\n <Button onClick={() => {\n tabsModal({\n rightOptions: <div>快捷操作:创建任务、分配成员、设置提醒</div>, items: [{\n label: \"项目文档\", key: \"documents\", children: <div>项目相关文档、合同、技术资料等文件的管理和查看</div>\n }, {\n label: \"团队协作\", key: \"collaboration\", children: <div>团队成员沟通记录、会议纪要、讨论内容等协作信息</div>\n }]\n });\n }}>hooks调用方式</Button>\n <Button onClick={() => {\n tabsModal({\n title: \"此title不展示\",\n rightOptions: ({ data }) => <Content list={data} />,\n withDecorator: (render) => <Fetch loader={() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([{ label: \"任务列表\", content: \"项目任务清单、完成状态、负责人和截止日期\" }, {\n label: \"进度报告\", content: \"项目进度百分比、已完成的任务、待办事项和风险提示\"\n }]);\n }, 1000);\n });\n }} render={({ data }) => render({ data })} />,\n items: [{\n label: \"任务管理\", key: \"tasks\", children: ({ data }) => <Content list={data} col={2} />\n }, {\n withDecorator: (render) => <Fetch loader={() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([{ label: \"资源分配\", content: \"项目资源使用情况、预算消耗、人力配置\" }, {\n label: \"风险跟踪\", content: \"项目风险列表、影响程度、应对措施和负责人\"\n }]);\n }, 1000);\n });\n }} render={({ data }) => render({ tabData: data })} />,\n label: \"资源与风险\",\n key: \"resources\",\n children: ({ data, tabData }) => <Content list={[...data, ...tabData]} col={2} />\n }]\n });\n }}>复杂数据加载</Button>\n </Space>;\n};\n\nrender(<PureGlobal><BaseExample /></PureGlobal>);\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_92\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n},{\n name: \"fetch\",\n packageName: \"@kne/react-fetch\",\n component: component_93\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_94\n}]\n},{\n title: `ModalButton数据加载弹窗`,\n description: `展示ModalButton组件的用法,点击按钮加载数据后弹出弹窗`,\n code: `const { ModalButton, TabsModalButton } = _Modal;\nconst { Space } = antd;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\nconst { default: FormInfo, Input, TextArea } = _FormInfo;\n\nconst api = {\n loader: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n { label: \"客户基本信息\", content: \"客户公司名称、联系人、联系电话、地址等基础信息\" },\n {\n label: \"合作记录\",\n content: \"历史合作项目、合作金额、合作状态、合同到期时间等合作相关信息\",\n },\n ]);\n }, 1000);\n });\n },\n};\n\nconst BaseExample = () => {\n return (\n <Space wrap>\n <ModalButton\n api={api}\n modalProps={({ data }) => {\n return {\n title: \"加载数据的弹窗\",\n children: <Content list={data} col={2} />,\n };\n }}\n >\n 点击加载数据\n </ModalButton>\n <TabsModalButton\n api={api}\n modalProps={({ data }) => {\n return {\n items: data.map(({ label, content }, index) => {\n return {\n key: index,\n children: content,\n label,\n };\n }),\n };\n }}\n >\n 点击加载数据的Tabs弹窗\n </TabsModalButton>\n </Space>\n );\n};\n\nrender(\n <PureGlobal>\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_92\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_94\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_90\n}]\n},{\n title: `业务场景示例`,\n description: `展示Modal组件在真实业务场景中的应用,包括用户管理、订单详情、产品多标签页和审批流程`,\n code: `const {default: Modal, useModal, TabsModal, useTabsModal, ModalButton, TabsModalButton} = _Modal;\nconst {default: FormInfo, useFormModal, fields} = _FormInfo;\nconst {useState, useCallback} = React;\nconst {\n Button,\n Space,\n message,\n Table,\n Input,\n Select,\n DatePicker,\n InputNumber,\n Descriptions,\n Tag,\n Avatar,\n Card,\n List,\n Divider\n} = antd;\n\n// 用户管理弹窗示例\nconst UserManagementModalExample = () => {\n const formModal = useFormModal();\n\n const handleAddUser = () => {\n const modalApi = formModal({\n title: \"添加用户\",\n size: \"large\",\n formProps: {\n onSubmit: (data) => {\n console.log(\"保存用户信息:\", data);\n \n // 模拟API调用\n message.success(\"用户信息保存成功\");\n modalApi.close();\n },\n },\n children: (<FormInfo\n list={[\n <fields.Input name=\"username\" label=\"用户名\" rule=\"REQ\"/>,\n <fields.Input name=\"realName\" label=\"真实姓名\" rule=\"REQ\"/>,\n <fields.Input name=\"email\" label=\"邮箱\" rule=\"EMAIL\"/>,\n <fields.Input name=\"phone\" label=\"手机号\" rule=\"PHONE\"/>,\n <fields.Select \n name=\"department\" \n label=\"部门\" \n rule=\"REQ\"\n options={[\n { label: \"技术部\", value: \"tech\" },\n { label: \"产品部\", value: \"product\" },\n { label: \"设计部\", value: \"design\" },\n { label: \"人力资源部\", value: \"hr\" },\n ]}\n />,\n <fields.DatePicker name=\"joinDate\" label=\"入职日期\" rule=\"REQ\"/>,\n <fields.TextArea name=\"remark\" label=\"备注\" />,\n ]}\n />),\n });\n };\n\n return (<Space direction=\"vertical\" style={{width: '100%'}}>\n <Button type=\"primary\" onClick={handleAddUser}>\n 添加新用户\n </Button>\n </Space>);\n};\n\n// 订单详情弹窗示例\nconst OrderDetailModalExample = () => {\n const modal = useModal();\n\n const showOrderDetail = useCallback((orderId) => {\n // 模拟加载订单数据\n modal({\n title: \\`订单详情 - #\\${orderId}\\`, width: 800, withDecorator: (render) => {\n return (<div>\n <div style={{background: '#f5f5f5', padding: '12px 16px', marginBottom: '16px'}}>\n <Space>\n <Tag color=\"blue\">待发货</Tag>\n <span>下单时间: 2023-06-15 14:30:22</span>\n </Space>\n </div>\n {render()}\n </div>);\n }, children: () => {\n const orderData = {\n id: orderId,\n customer: '张三',\n phone: '13800138000',\n address: '北京市朝阳区xxx街道xxx号',\n products: [{id: 1, name: '商品A', price: 299, quantity: 2}, {\n id: 2, name: '商品B', price: 199, quantity: 1\n }, {id: 3, name: '商品C', price: 99, quantity: 3},],\n totalAmount: 994,\n paymentMethod: '在线支付',\n deliveryMethod: '快递配送',\n remark: '请在工作日送达',\n };\n\n return (<div>\n <Descriptions title=\"订单信息\" bordered column={2}>\n <Descriptions.Item label=\"订单号\">{orderData.id}</Descriptions.Item>\n <Descriptions.Item label=\"下单时间\">2023-06-15 14:30:22</Descriptions.Item>\n <Descriptions.Item label=\"收货人\">{orderData.customer}</Descriptions.Item>\n <Descriptions.Item label=\"联系电话\">{orderData.phone}</Descriptions.Item>\n <Descriptions.Item label=\"收货地址\" span={2}>{orderData.address}</Descriptions.Item>\n <Descriptions.Item label=\"支付方式\">{orderData.paymentMethod}</Descriptions.Item>\n <Descriptions.Item label=\"配送方式\">{orderData.deliveryMethod}</Descriptions.Item>\n </Descriptions>\n\n <div style={{marginTop: 16}}>\n <h4>商品清单</h4>\n <Table\n dataSource={orderData.products}\n pagination={false}\n columns={[{title: '商品名称', dataIndex: 'name', key: 'name'}, {\n title: '单价(元)', dataIndex: 'price', key: 'price'\n }, {title: '数量', dataIndex: 'quantity', key: 'quantity'}, {\n title: '小计(元)',\n key: 'subtotal',\n render: (_, record) => record.price * record.quantity\n },]}\n summary={() => (<Table.Summary>\n <Table.Summary.Row>\n <Table.Summary.Cell index={0} colSpan={3}>\n <strong>总计</strong>\n </Table.Summary.Cell>\n <Table.Summary.Cell index={1}>\n <strong>{orderData.totalAmount}元</strong>\n </Table.Summary.Cell>\n </Table.Summary.Row>\n </Table.Summary>)}\n />\n </div>\n\n <div style={{marginTop: 16}}>\n <h4>备注</h4>\n <p>{orderData.remark}</p>\n </div>\n </div>);\n }, footerButtons: [{\n children: '打印订单', onClick: () => message.info(\"打印功能待实现\"),\n }, {\n children: '发货', type: 'primary', onClick: async () => {\n try {\n await new Promise(resolve => setTimeout(resolve, 1000));\n message.success(\"订单已发货\");\n } catch (error) {\n message.error(\"发货失败,请重试\");\n }\n },\n },],\n });\n }, [modal]);\n\n const orders = [{id: 'ORD20230615001', customer: '张三', amount: 299, status: 'pending'}, {\n id: 'ORD20230615002', customer: '李四', amount: 598, status: 'shipped'\n }, {id: 'ORD20230615003', customer: '王五', amount: 398, status: 'completed'},];\n\n const statusMap = {\n pending: {text: '待发货', color: 'orange'},\n shipped: {text: '已发货', color: 'blue'},\n completed: {text: '已完成', color: 'green'},\n };\n\n return (<Card title=\"订单列表\" size=\"small\">\n <Table\n dataSource={orders}\n pagination={false}\n columns={[{title: '订单号', dataIndex: 'id', key: 'id'}, {\n title: '客户', dataIndex: 'customer', key: 'customer'\n }, {title: '金额', dataIndex: 'amount', key: 'amount'}, {\n title: '状态',\n dataIndex: 'status',\n key: 'status',\n render: (status) => (<Tag color={statusMap[status]?.color}>\n {statusMap[status]?.text}\n </Tag>),\n }, {\n title: '操作',\n key: 'action',\n render: (_, record) => (<Button type=\"link\" onClick={() => showOrderDetail(record.id)}>\n 查看详情\n </Button>),\n },]}\n />\n </Card>);\n};\n\n// 审批流程弹窗示例\nconst ApprovalProcessModalExample = () => {\n const modal = useModal();\n\n const showApprovalModal = useCallback((requestId) => {\n modal({\n title: \"审批申请\", width: 700, withDecorator: (render) => {\n return (<div>\n <div style={{\n background: '#f0f8ff', padding: '12px 16px', marginBottom: '16px', border: '1px solid #91d5ff'\n }}>\n <Space direction=\"vertical\" size=\"small\">\n <div><strong>申请编号:</strong> {requestId}</div>\n <div><strong>申请时间:</strong> 2023-06-15 09:30:00</div>\n <div><strong>申请人:</strong> 张三 (技术部)</div>\n </Space>\n </div>\n {render()}\n </div>);\n }, children: () => {\n return (<div>\n <Descriptions title=\"申请信息\" bordered column={2}>\n <Descriptions.Item label=\"申请类型\">费用报销</Descriptions.Item>\n <Descriptions.Item label=\"申请金额\">¥2,580.00</Descriptions.Item>\n <Descriptions.Item label=\"费用类型\">差旅费</Descriptions.Item>\n <Descriptions.Item label=\"发生时间\">2023-06-10 至 2023-06-12</Descriptions.Item>\n <Descriptions.Item label=\"费用明细\" span={2}>\n <div>交通费: ¥800.00</div>\n <div>住宿费: ¥1,200.00</div>\n <div>餐饮费: ¥580.00</div>\n </Descriptions.Item>\n <Descriptions.Item label=\"申请原因\" span={2}>\n 前往上海参加技术交流会议,包含交通、住宿和餐饮费用。\n </Descriptions.Item>\n </Descriptions>\n\n <Divider/>\n\n <div>\n <h4>审批流程</h4>\n <List\n dataSource={[{\n title: '部门经理审批',\n name: '李经理',\n status: 'completed',\n time: '2023-06-15 10:15:00',\n remark: '同意申请'\n }, {\n title: '财务审批',\n name: '王会计',\n status: 'completed',\n time: '2023-06-15 14:30:00',\n remark: '费用明细清晰,同意报销'\n }, {\n title: '总经理审批', name: '赵总', status: 'pending', time: '-', remark: '待审批'\n },]}\n renderItem={(item) => (<List.Item>\n <List.Item.Meta\n avatar={<Avatar\n style={{backgroundColor: item.status === 'completed' ? '#52c41a' : '#faad14'}}>\n {item.name[0]}\n </Avatar>}\n title={<Space>\n {item.title}\n <Tag color={item.status === 'completed' ? 'green' : 'orange'}>\n {item.status === 'completed' ? '已完成' : '待审批'}\n </Tag>\n </Space>}\n description={<div>\n <div>审批人: {item.name}</div>\n <div>审批时间: {item.time}</div>\n <div>审批意见: {item.remark}</div>\n </div>}\n />\n </List.Item>)}\n />\n </div>\n </div>);\n }, footerButtons: [{\n children: '打印申请', onClick: () => message.info(\"打印功能待实现\"),\n }, {\n children: '驳回', onClick: () => message.success(\"申请已驳回\"),\n }, {\n children: '批准', type: 'primary', onClick: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n message.success(\"申请已批准\");\n resolve();\n }, 1000);\n });\n },\n },],\n });\n }, [modal]);\n\n return (<Card title=\"审批列表\" size=\"small\">\n <Space direction=\"vertical\" style={{width: '100%'}}>\n {[{\n id: 'REQ20230615001', type: '费用报销', applicant: '张三', amount: 2580, status: 'pending'\n }, {\n id: 'REQ20230615002', type: '请假申请', applicant: '李四', days: 3, status: 'approved'\n }, {\n id: 'REQ20230615003', type: '采购申请', applicant: '王五', amount: 15000, status: 'rejected'\n },].map((request) => (<Card key={request.id} size=\"small\" style={{marginBottom: 8}}>\n <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>\n <div>\n <div style={{fontWeight: 'bold', marginBottom: 4}}>{request.type}</div>\n <div>申请人: {request.applicant}</div>\n {request.amount && <div>金额: ¥{request.amount}</div>}\n {request.days && <div>天数: {request.days}天</div>}\n <div>\n 状态:\n <Tag\n color={request.status === 'pending' ? 'orange' : request.status === 'approved' ? 'green' : 'red'}>\n {request.status === 'pending' ? '待审批' : request.status === 'approved' ? '已批准' : '已驳回'}\n </Tag>\n </div>\n </div>\n <Button type=\"primary\" onClick={() => showApprovalModal(request.id)}>\n 处理审批\n </Button>\n </div>\n </Card>))}\n </Space>\n </Card>);\n};\n\nconst BusinessScenarioExamples = () => {\n return (<Space direction=\"vertical\" style={{width: '100%'}} size=\"large\">\n <UserManagementModalExample/>\n <OrderDetailModalExample/>\n <ApprovalProcessModalExample/>\n </Space>);\n};\n\nrender(<BusinessScenarioExamples/>);\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"_FormInfo\",\n packageName: \"@components/FormInfo\",\n component: component_90\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n}]\n},{\n title: `数据加载弹窗`,\n description: `展示使用withDecorator实现弹窗加载数据或加载远程组件的逻辑`,\n code: `const { default: Modal, useModal } = _Modal;\nconst { useState } = React;\nconst { Button, Space } = antd;\nconst { default: Fetch } = fetch;\nconst { PureGlobal } = global;\nconst { default: Content } = _Content;\n\nconst BaseExample = () => {\n const modal = useModal();\n const [open, setOpen] = useState(false);\n return (\n <Space wrap>\n <Modal\n title=\"组件调用方式\"\n withDecorator={(render) => (\n <Fetch\n loader={() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"用户基本信息\",\n content: \"展示用户的姓名、邮箱、部门等基础信息,用于身份识别和管理\",\n },\n {\n label: \"联系信息\",\n content: \"电话号码、地址、紧急联系人等通讯信息,便于工作沟通和紧急联络\",\n },\n ]);\n }, 1000);\n });\n }}\n render={({ data }) => render({ data })}\n />\n )}\n open={open}\n onClose={() => {\n setOpen(false);\n }}\n >\n {({ data }) => <Content list={data} col={2} />}\n </Modal>\n <Button\n onClick={() => {\n setOpen(true);\n }}\n >\n 组件调用方式\n </Button>\n <Button\n onClick={() => {\n modal({\n title: \"hooks调用方式\",\n withDecorator: (render) => (\n <Fetch\n loader={() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"订单详情\",\n content: \"订单编号、下单时间、客户信息、订单状态等订单基本信息\",\n },\n {\n label: \"支付信息\",\n content: \"支付方式、支付时间、支付金额、交易流水号等支付相关信息\",\n },\n ]);\n }, 1000);\n });\n }}\n render={({ data }) => render({ data })}\n />\n ),\n children: ({ data }) => <Content list={data} col={2} />,\n });\n }}\n >\n hooks调用方式\n </Button>\n <Button\n onClick={() => {\n modal({\n title: (props) => {\n return \"hooks调用方式\";\n },\n withDecorator: (render) => (\n <Fetch\n loader={() => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n {\n label: \"订单详情\",\n content: \"订单编号、下单时间、客户信息、订单状态等订单基本信息\",\n },\n {\n label: \"支付信息\",\n content: \"支付方式、支付时间、支付金额、交易流水号等支付相关信息\",\n },\n ]);\n }, 1000);\n });\n }}\n render={({ data }) => render({ data })}\n />\n ),\n children: ({ data }) => <Content list={data} col={2} />,\n });\n }}\n >\n hooks title调用方式\n </Button>\n </Space>\n );\n};\n\nrender(\n <PureGlobal>\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_92\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n},{\n name: \"fetch\",\n packageName: \"@kne/react-fetch\",\n component: component_93\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_94\n}]\n},{\n title: `消息确认和提示`,\n description: `展示命令式调用的消息确认和提示功能`,\n code: `const { default: Modal, useConfirmModal } = _Modal;\nconst { useState } = React;\nconst { Button, Space, message } = antd;\nconst { PureGlobal } = global;\nconst BaseExample = () => {\n const confirmModal = useConfirmModal();\n return (\n <Space wrap>\n <Button\n onClick={() => {\n confirmModal({\n danger: true,\n type: \"confirm\",\n title: \"确定要删除该记录吗?\",\n message:\n \"此操作将永久删除该记录,相关数据将无法恢复。请确认是否继续删除操作?\",\n });\n }}\n >\n confirm\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"confirm\",\n confirmType: \"warning\",\n title: \"确定要编辑此内容吗?\",\n message:\n \"编辑后需要重新提交审核,未保存的修改将丢失。请确认是否继续编辑?\",\n });\n }}\n >\n confirm 警告\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"info\",\n title: \"操作提示\",\n message:\n \"该操作将更新系统配置,可能影响其他用户的使用。建议在非工作时间进行此操作。\",\n });\n }}\n >\n info\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"info\",\n message:\n \"数据已保存成功,系统将在后台进行同步处理,请稍候查看处理结果。\",\n });\n }}\n >\n info无标题\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"success\",\n title: \"操作成功\",\n message:\n \"恭喜!您的操作已成功完成。系统已发送通知邮件给相关团队成员。\",\n });\n }}\n >\n success\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"warning\",\n title: \"操作警告\",\n message:\n \"检测到数据异常,继续操作可能导致数据不一致。建议先备份数据或联系技术支持。\",\n });\n }}\n >\n warning\n </Button>\n <Button\n onClick={() => {\n confirmModal({\n type: \"error\",\n title: \"操作失败\",\n message:\n \"系统处理出错,请检查网络连接或联系系统管理员。错误代码:ERR-500\",\n });\n }}\n >\n error\n </Button>\n </Space>\n );\n};\n\nrender(\n <PureGlobal>\n <BaseExample />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_92\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n},{\n name: \"fetch\",\n packageName: \"@kne/react-fetch\",\n component: component_93\n},{\n name: \"_Content\",\n packageName: \"@components/Content\",\n component: component_94\n}]\n},{\n title: `childrenRef的使用`,\n description: `展示如何使用childrenRef获取弹窗内容的引用`,\n code: `const { default: Modal, useModal } = _Modal;\nconst { Button } = antd;\nconst BaseExample = () => {\n const modal = useModal();\n\n return (\n <Button\n onClick={() => {\n modal({\n title: \"示例弹框\",\n children: ({ childrenRef }) => {\n return (\n <div ref={childrenRef}>\n 这是使用childrenRef的示例弹窗内容,展示了如何通过ref获取子组件的DOM引用。\n </div>\n );\n },\n onConfirm: (e, { childrenRef }) => {\n console.log(childrenRef.current);\n },\n });\n }}\n >\n 点击弹出弹框\n </Button>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Modal\",\n packageName: \"@components/Modal\",\n component: component_89\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_91\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_95 from '@components/Navigation';\nimport * as component_96 from '@components/Global';\nimport * as component_97 from 'antd';\nconst readmeConfig = {\n name: `Navigation`,\n summary: `<h3>概述</h3>\n<p>Navigation 是一个基于 Ant Design Menu 组件的顶部导航栏组件,支持权限控制、响应式布局和自定义配置。适用于需要顶部导航的各种应用场景。</p>\n<h3>何时使用</h3>\n<p>系统的顶部导航,一级导航项偏左靠近 logo 放置,辅助菜单偏右放置。</p>\n<h3>特点</h3>\n<ul>\n<li>集成了Permissions权限判断,可以通过权限列表来判断导航项是否显示</li>\n<li>在屏幕显示不了全部的一级导航时可以自动将后面的导航项收起到更多下拉菜单里面</li>\n<li>支持自定义导航项点击处理和路由跳转</li>\n<li>自动更新页面标题,基于当前导航项配置</li>\n</ul>`,\n \n \n api: `<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>base</td>\n<td>导航基础路径</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>defaultTitle</td>\n<td>默认页面标题</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>headerLogo</td>\n<td>导航栏Logo配置</td>\n<td>object</td>\n<td>内置logo</td>\n</tr>\n<tr>\n<td>indexLabel</td>\n<td>首页导航标签</td>\n<td>string</td>\n<td>ReactNode</td>\n</tr>\n<tr>\n<td>isFixed</td>\n<td>是否固定在页面顶部</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>list</td>\n<td>导航菜单项配置</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>navigateTo</td>\n<td>自定义导航函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>导航切换回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>overflowedIndicator</td>\n<td>导航项溢出时的指示器</td>\n<td>ReactNode</td>\n<td>默认\"更多\"下拉</td>\n</tr>\n<tr>\n<td>permissions</td>\n<td>当前用户的权限列表</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>rightOptions</td>\n<td>导航栏右侧区域内容</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>showIndex</td>\n<td>是否显示首页导航</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n</tbody>\n</table>\n<h3>list项配置</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>key</td>\n<td>导航项唯一标识</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>导航项显示标题</td>\n<td>string</td>\n<td>ReactNode</td>\n</tr>\n<tr>\n<td>path</td>\n<td>导航项路径</td>\n<td>string</td>\n<td>function</td>\n</tr>\n<tr>\n<td>permission</td>\n<td>权限控制,可以是字符串、数组或函数</td>\n<td>string</td>\n<td>array</td>\n</tr>\n<tr>\n<td>icon</td>\n<td>导航项图标</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: true,\n className: `Navigation_84649`,\n style: `.Navigation_84649 .fold-items {\n width: 600px;\n}`,\n list: [{\n title: `基础导航`,\n description: `展示Navigation组件的基本用法,包括基础导航和权限控制`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\n\nconst menuList = [\n {\n key: \"client\",\n title: \"客户\",\n path: \"/client\",\n permission: \"client:client:look\",\n },\n {\n key: \"position\",\n title: \"职位\",\n path: \"/position\",\n permission: \"jd:job:look\",\n },\n {\n key: \"ats\",\n title: \"招聘流程\",\n path: \"/ats\",\n },\n {\n key: \"talent\",\n title: \"人才库\",\n permission: \"cv:cv:look\",\n path: \"/talent\",\n },\n {\n key: \"contract\",\n title: \"合同\",\n permission: \"contract:mgr:look\",\n path: \"/contract\",\n },\n {\n key: \"payment\",\n title: \"付款信息\",\n permission: \"payment:mgr:look\",\n path: \"/payment\",\n },\n {\n key: \"invoice-center\",\n title: \"开票\",\n permission: \"client:invoice:center\",\n path: \"/invoice-center\",\n },\n {\n key: \"invoice-manage\",\n title: \"发票管理\",\n permission: \"client:invoice:manager\",\n path: \"/invoice-manage\",\n },\n {\n key: \"setting\",\n title: \"设置\",\n permission: (permissions) =>\n permissions.some(\n (x) =>\n [\n \"system:permissions:mgr\",\n \"system:org:mgr\",\n \"system:user:mgr\",\n ].indexOf(x) !== -1\n ),\n path: \"/setting\",\n },\n];\n\nrender(\n <PureGlobal>\n <Navigation\n list={menuList}\n isFixed={false}\n permissions={[\n \"client:client:look\",\n \"jd:job:look\",\n \"cv:cv:look\",\n \"contract:mgr:look\",\n \"payment:mgr:look\",\n \"client:invoice:center\",\n \"client:invoice:manager\",\n \"system:permissions:mgr\",\n ]}\n />\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n}]\n},{\n title: `导航功能特性`,\n description: `展示Navigation组件的各种功能特性,包括权限控制、自定义右侧选项、图标和标题`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { Card, Space, Avatar, Button, Dropdown, Badge } = antd;\nconst { UserOutlined, SettingOutlined, BellOutlined, DownOutlined } = antd.icons;\nconst { useState } = React;\n\n// 基础导航示例\nconst BasicNavigationExample = () => {\n const menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n },\n {\n key: \"customers\",\n title: \"客户管理\",\n path: \"/customers\",\n },\n ];\n\n return (\n <Card title=\"基础导航\" size=\"small\">\n <Navigation\n list={menuList}\n isFixed={false}\n />\n </Card>\n );\n};\n\n// 带权限控制的导航示例\nconst PermissionNavigationExample = () => {\n const [userPermissions, setUserPermissions] = useState([\n \"dashboard:view\",\n \"products:view\",\n \"orders:view\"\n ]);\n \n const menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n permission: \"dashboard:view\",\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n permission: \"products:view\",\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n permission: \"orders:view\",\n },\n {\n key: \"customers\",\n title: \"客户管理\",\n path: \"/customers\",\n permission: \"customers:view\",\n },\n {\n key: \"settings\",\n title: \"系统设置\",\n path: \"/settings\",\n permission: (permissions) => permissions.some(p => p.includes(\"admin\")),\n },\n ];\n\n const userMenuItems = [\n {\n key: \"admin-permissions\",\n label: \"管理员权限\",\n onClick: () => {\n setUserPermissions([\n \"dashboard:view\",\n \"products:view\",\n \"orders:view\",\n \"customers:view\",\n \"admin:full\"\n ]);\n },\n },\n {\n key: \"user-permissions\",\n label: \"普通用户权限\",\n onClick: () => {\n setUserPermissions([\n \"dashboard:view\",\n \"products:view\",\n \"orders:view\"\n ]);\n },\n },\n ];\n\n return (\n <Card title=\"权限控制导航\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Dropdown menu={{ items: userMenuItems }} placement=\"bottomLeft\">\n <Button>切换用户权限</Button>\n </Dropdown>\n <Navigation\n list={menuList}\n isFixed={false}\n permissions={userPermissions}\n />\n </Space>\n </Card>\n );\n};\n\n// 自定义右侧选项的导航示例\nconst CustomOptionsNavigationExample = () => {\n const menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n },\n ];\n\n const rightOptions = (\n <Space size=\"middle\">\n <Badge count={5} size=\"small\">\n <Button type=\"text\" icon={<BellOutlined />} />\n </Badge>\n <Avatar icon={<UserOutlined />} />\n <Dropdown menu={{ \n items: [\n { key: 'profile', label: '个人资料' },\n { key: 'settings', label: '系统设置' },\n { key: 'logout', label: '退出登录' },\n ]\n }}>\n <Button type=\"text\" icon={<DownOutlined />} />\n </Dropdown>\n </Space>\n );\n\n return (\n <Card title=\"自定义右侧选项\" size=\"small\">\n <Navigation\n list={menuList}\n isFixed={false}\n rightOptions={rightOptions}\n />\n </Card>\n );\n};\n\n// 带图标的导航示例\nconst IconNavigationExample = () => {\n const { DashboardOutlined, ShoppingOutlined, FileTextOutlined, TeamOutlined } = antd.icons;\n \n const menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n icon: <DashboardOutlined />,\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n icon: <ShoppingOutlined />,\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n icon: <FileTextOutlined />,\n },\n {\n key: \"customers\",\n title: \"客户管理\",\n path: \"/customers\",\n icon: <TeamOutlined />,\n },\n ];\n\n return (\n <Card title=\"带图标导航\" size=\"small\">\n <Navigation\n list={menuList}\n isFixed={false}\n />\n </Card>\n );\n};\n\n// 自定义标题的导航示例\nconst CustomTitleNavigationExample = () => {\n const menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n },\n ];\n\n return (\n <Card title=\"自定义标题\" size=\"small\">\n <Navigation\n list={menuList}\n isFixed={false}\n defaultTitle=\"企业管理系统\"\n />\n </Card>\n );\n};\n\nconst NavigationFeaturesExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <BasicNavigationExample />\n <PermissionNavigationExample />\n <CustomOptionsNavigationExample />\n <IconNavigationExample />\n <CustomTitleNavigationExample />\n </Space>\n );\n};\n\nrender(<NavigationFeaturesExample />);\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n},{\n title: `折叠导航`,\n description: `展示Navigation组件在空间不足时的折叠功能`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\n\nconst menuList = [\n {\n key: \"client\",\n title: \"客户\",\n path: \"/client\",\n permission: \"client:client:look\",\n },\n {\n key: \"position\",\n title: \"职位\",\n path: \"/position\",\n permission: \"jd:job:look\",\n },\n {\n key: \"ats\",\n title: \"招聘流程\",\n path: \"/ats\",\n },\n {\n key: \"talent\",\n title: \"人才库\",\n permission: \"cv:cv:look\",\n path: \"/talent\",\n },\n {\n key: \"contract\",\n title: \"合同\",\n permission: \"contract:mgr:look\",\n path: \"/contract\",\n },\n {\n key: \"payment\",\n title: \"付款信息\",\n permission: \"payment:mgr:look\",\n path: \"/payment\",\n },\n {\n key: \"invoice-center\",\n title: \"开票\",\n permission: \"client:invoice:center\",\n path: \"/invoice-center\",\n },\n {\n key: \"invoice-manage\",\n title: \"发票管理\",\n permission: \"client:invoice:manager\",\n path: \"/invoice-manage\",\n },\n {\n key: \"setting\",\n title: \"设置\",\n permission: (permissions) =>\n permissions.some(\n (x) =>\n [\n \"system:permissions:mgr\",\n \"system:org:mgr\",\n \"system:user:mgr\",\n ].indexOf(x) !== -1\n ),\n path: \"/setting\",\n },\n];\n\nrender(\n <PureGlobal>\n <div className=\"fold-items\">\n <Navigation\n isFixed={false}\n list={menuList}\n permissions={[\n \"client:client:look\",\n \"jd:job:look\",\n \"cv:cv:look\",\n \"contract:mgr:look\",\n \"payment:mgr:look\",\n \"client:invoice:center\",\n \"client:invoice:manager\",\n \"system:permissions:mgr\",\n ]}\n />\n </div>\n </PureGlobal>\n);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n}]\n},{\n title: `权限控制`,\n description: `展示Navigation组件的权限控制功能`,\n code: `const { useState } = React;\nconst { PureGlobal } = global;\nconst { default: Navigation } = _Navigation;\nconst { Checkbox, Space } = antd;\n\nconst menuList = [\n {\n key: \"client\",\n title: \"客户\",\n path: \"/client\",\n permission: \"client:client:look\",\n },\n {\n key: \"position\",\n title: \"职位\",\n path: \"/position\",\n permission: \"jd:job:look\",\n },\n {\n key: \"ats\",\n title: \"招聘流程\",\n path: \"/ats\",\n },\n {\n key: \"talent\",\n title: \"人才库\",\n permission: \"cv:cv:look\",\n path: \"/talent\",\n },\n {\n key: \"contract\",\n title: \"合同\",\n permission: \"contract:mgr:look\",\n path: \"/contract\",\n },\n {\n key: \"payment\",\n title: \"付款信息\",\n permission: \"payment:mgr:look\",\n path: \"/payment\",\n },\n {\n key: \"invoice-center\",\n title: \"开票\",\n permission: \"client:invoice:center\",\n path: \"/invoice-center\",\n },\n {\n key: \"invoice-manage\",\n title: \"发票管理\",\n permission: \"client:invoice:manager\",\n path: \"/invoice-manage\",\n },\n {\n key: \"setting\",\n title: \"设置\",\n permission: (permissions) =>\n permissions.some(\n (x) =>\n [\n \"system:permissions:mgr\",\n \"system:org:mgr\",\n \"system:user:mgr\",\n ].indexOf(x) !== -1\n ),\n path: \"/setting\",\n },\n];\n\nconst Example = () => {\n const [permissions, setPermissions] = useState([]);\n return (\n <PureGlobal>\n <Space className=\"container\" direction=\"vertical\" size={32}>\n <Navigation isFixed={false} list={menuList} permissions={permissions} />\n <Checkbox.Group\n value={permissions}\n options={[\n \"client:client:look\",\n \"jd:job:look\",\n \"cv:cv:look\",\n \"contract:mgr:look\",\n \"payment:mgr:look\",\n \"client:invoice:center\",\n \"client:invoice:manager\",\n \"system:permissions:mgr\",\n ]}\n onChange={(values) => {\n setPermissions(values);\n }}\n />\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<Example />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n}]\n},{\n title: `自定义配置`,\n description: `展示Navigation组件的自定义基础配置,包括base、headerLogo、indexLabel、rightOptions等属性`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { Avatar, Badge, Dropdown, Space } = antd;\n\nconst menuList = [\n {\n key: \"dashboard\",\n title: \"数据概览\",\n path: \"/dashboard\",\n icon: <span style={{ fontSize: 16 }}>📊</span>,\n },\n {\n key: \"project\",\n title: \"项目管理\",\n path: \"/project\",\n icon: <span style={{ fontSize: 16 }}>📁</span>,\n },\n {\n key: \"contract\",\n title: \"合同管理\",\n path: \"/contract\",\n icon: <span style={{ fontSize: 16 }}>📄</span>,\n },\n {\n key: \"invoice\",\n title: \"发票管理\",\n path: \"/invoice\",\n icon: <span style={{ fontSize: 16 }}>🧾</span>,\n },\n {\n key: \"approval\",\n title: \"审批中心\",\n path: \"/approval\",\n icon: <span style={{ fontSize: 16 }}>✅</span>,\n },\n {\n key: \"report\",\n title: \"报表分析\",\n path: \"/report\",\n icon: <span style={{ fontSize: 16 }}>📈</span>,\n },\n];\n\nconst CustomConfigExample = () => {\n return (\n <PureGlobal>\n <Navigation\n base=\"/app\"\n className=\"custom-navigation\"\n defaultTitle=\"企业管理系统\"\n headerLogo={{\n src: \"https://api.dicebear.com/7.x/icons/svg?seed=company\",\n width: 32,\n height: 32,\n }}\n indexLabel=\"🏠 首页\"\n isFixed={false}\n list={menuList}\n showIndex={true}\n permissions={[\n \"dashboard:view\",\n \"project:view\",\n \"contract:view\",\n \"invoice:view\",\n \"approval:view\",\n \"report:view\",\n ]}\n rightOptions={\n <Space size=\"middle\">\n <Badge count={5}>\n <span style={{ fontSize: 18, cursor: \"pointer\" }}>🔔</span>\n </Badge>\n <Dropdown\n menu={{\n items: [\n { key: \"profile\", label: \"个人设置\" },\n { key: \"logout\", label: \"退出登录\" },\n ],\n }}\n >\n <Avatar\n size=\"small\"\n src=\"https://api.dicebear.com/7.x/avataaars/svg?seed=manager\"\n style={{ cursor: \"pointer\" }}\n />\n </Dropdown>\n </Space>\n }\n />\n </PureGlobal>\n );\n};\n\nrender(<CustomConfigExample />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n},{\n title: `导航事件`,\n description: `展示Navigation组件的导航事件处理,包括onChange回调和navigateTo自定义导航函数`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { message } = antd;\n\nconst menuList = [\n {\n key: \"home\",\n title: \"首页\",\n path: \"/\",\n },\n {\n key: \"client\",\n title: \"客户管理\",\n path: \"/client\",\n permission: \"client:view\",\n },\n {\n key: \"project\",\n title: \"项目管理\",\n path: \"/project\",\n permission: \"project:view\",\n },\n {\n key: \"talent\",\n title: \"人才库\",\n path: \"/talent\",\n permission: [\"talent:view\", \"resume:view\"],\n },\n];\n\nconst NavigationEventsExample = () => {\n return (\n <PureGlobal>\n <Navigation\n list={menuList}\n isFixed={false}\n permissions={[\"client:view\", \"project:view\", \"talent:view\", \"resume:view\"]}\n onChange={(path) => {\n message.success(\\`导航到路径: \\${path}\\`);\n }}\n navigateTo={(path) => {\n message.info(\\`自定义导航: \\${path}\\`);\n }}\n />\n </PureGlobal>\n );\n};\n\nrender(<NavigationEventsExample />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n},{\n title: `溢出指示器`,\n description: `展示Navigation组件的自定义溢出指示器和大量菜单项的处理`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { Space } = antd;\n\nconst menuList = [\n { key: \"home\", title: \"首页\", path: \"/\" },\n { key: \"module1\", title: \"业务模块一\", path: \"/module1\" },\n { key: \"module2\", title: \"业务模块二\", path: \"/module2\" },\n { key: \"module3\", title: \"业务模块三\", path: \"/module3\" },\n { key: \"module4\", title: \"业务模块四\", path: \"/module4\" },\n { key: \"module5\", title: \"业务模块五\", path: \"/module5\" },\n { key: \"module6\", title: \"业务模块六\", path: \"/module6\" },\n { key: \"module7\", title: \"业务模块七\", path: \"/module7\" },\n { key: \"module8\", title: \"业务模块八\", path: \"/module8\" },\n { key: \"module9\", title: \"业务模块九\", path: \"/module9\" },\n { key: \"module10\", title: \"业务模块十\", path: \"/module10\" },\n { key: \"module11\", title: \"业务模块十一\", path: \"/module11\" },\n { key: \"module12\", title: \"业务模块十二\", path: \"/module12\" },\n { key: \"module13\", title: \"业务模块十三\", path: \"/module13\" },\n { key: \"module14\", title: \"业务模块十四\", path: \"/module14\" },\n { key: \"module15\", title: \"业务模块十五\", path: \"/module15\" },\n];\n\nconst OverflowIndicatorExample = () => {\n return (\n <PureGlobal>\n <Navigation\n list={menuList}\n isFixed={false}\n showIndex={false}\n overflowedIndicator={\n <Space size={4}>\n <span>更多菜单</span>\n <span style={{ fontSize: 12 }}>▼</span>\n </Space>\n }\n />\n </PureGlobal>\n );\n};\n\nrender(<OverflowIndicatorExample />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n},{\n title: `移动端适配`,\n description: `展示Navigation组件在移动端设备上的响应式布局`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { Space, Switch, Divider } = antd;\n\nconst menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n icon: <span style={{ fontSize: 16 }}>📊</span>,\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n icon: <span style={{ fontSize: 16 }}>📦</span>,\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n icon: <span style={{ fontSize: 16 }}>📋</span>,\n },\n {\n key: \"customers\",\n title: \"客户管理\",\n path: \"/customers\",\n icon: <span style={{ fontSize: 16 }}>👥</span>,\n },\n {\n key: \"settings\",\n title: \"系统设置\",\n path: \"/settings\",\n icon: <span style={{ fontSize: 16 }}>⚙️</span>,\n },\n];\n\nconst MobileResponsiveExample = () => {\n const [forceMobile, setForceMobile] = React.useState(undefined);\n\n return (\n <PureGlobal>\n <div style={{ maxWidth: '100%' }}>\n <div style={{ marginBottom: 16, padding: 16, background: '#f0f5ff' }}>\n <Space direction=\"vertical\" size={12}>\n <div style={{ fontSize: 14, color: '#666' }}>\n <strong>移动端模式控制:</strong>\n </div>\n <Space>\n <span>自动检测(根据窗口宽度)</span>\n <Switch\n checked={forceMobile === true}\n onChange={(checked) => setForceMobile(checked)}\n checkedChildren=\"强制移动端\"\n unCheckedChildren=\"自动\"\n />\n </Space>\n <div style={{ fontSize: 12, color: '#999' }}>\n 开启开关可强制切换到移动端布局,关闭则根据窗口宽度自动检测\n </div>\n </Space>\n </div>\n\n <Navigation\n list={menuList}\n isFixed={false}\n defaultTitle=\"企业管理系统\"\n isMobile={forceMobile}\n />\n\n <div style={{ marginTop: 24, padding: 16, background: '#f5f5f5' }}>\n <p>1. 调整浏览器窗口宽度至小于 768px,导航将自动切换为移动端模式</p>\n <p>2. 或者使用上方开关强制指定为移动端模式</p>\n <p>3. 在移动端模式下,导航菜单将显示为汉堡菜单,点击后从右侧滑出</p>\n </div>\n </div>\n </PureGlobal>\n );\n};\n\nrender(<MobileResponsiveExample />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n},{\n title: `强制移动端模式`,\n description: `展示如何通过isMobile属性强制指定导航栏的显示模式`,\n code: `const { default: Navigation } = _Navigation;\nconst { PureGlobal } = global;\nconst { Space, Switch } = antd;\nconst { useState } = React;\n\nconst menuList = [\n {\n key: \"dashboard\",\n title: \"仪表盘\",\n path: \"/dashboard\",\n icon: <span style={{ fontSize: 16 }}>📊</span>,\n },\n {\n key: \"products\",\n title: \"产品管理\",\n path: \"/products\",\n icon: <span style={{ fontSize: 16 }}>📦</span>,\n },\n {\n key: \"orders\",\n title: \"订单管理\",\n path: \"/orders\",\n icon: <span style={{ fontSize: 16 }}>📋</span>,\n },\n {\n key: \"customers\",\n title: \"客户管理\",\n path: \"/customers\",\n icon: <span style={{ fontSize: 16 }}>👥</span>,\n },\n {\n key: \"settings\",\n title: \"系统设置\",\n path: \"/settings\",\n icon: <span style={{ fontSize: 16 }}>⚙️</span>,\n },\n];\n\nconst ForceMobileExample = () => {\n const [isMobile, setIsMobile] = useState(false);\n\n return (\n <PureGlobal>\n <div style={{ maxWidth: '100%' }}>\n <div style={{ marginBottom: 16, padding: 16, background: '#f0f5ff' }}>\n <Space direction=\"vertical\" size={12}>\n <div style={{ fontSize: 14, color: '#666' }}>\n <strong>强制移动端模式:</strong>\n </div>\n <Switch\n checked={isMobile}\n onChange={setIsMobile}\n checkedChildren=\"开启移动端\"\n unCheckedChildren=\"桌面端\"\n />\n <div style={{ fontSize: 12, color: '#999' }}>\n 通过 <code>isMobile</code> 属性可以强制指定导航栏的显示模式\n </div>\n </Space>\n </div>\n\n <Navigation\n list={menuList}\n isFixed={false}\n defaultTitle=\"企业管理系统\"\n isMobile={isMobile}\n />\n\n <div style={{ marginTop: 24, padding: 16, background: '#f5f5f5' }}>\n <p>点击上方开关可以强制切换导航栏的显示模式:</p>\n <ul style={{ marginTop: 8, paddingLeft: 20 }}>\n <li>关闭开关:显示桌面端水平菜单</li>\n <li>打开开关:显示移动端汉堡菜单(点击后显示下拉菜单)</li>\n </ul>\n <p style={{ marginTop: 8, color: '#666' }}>\n 注意:当不指定 <code>isMobile</code> 属性时,组件会根据窗口宽度自动检测\n </p>\n </div>\n </div>\n </PureGlobal>\n );\n};\n\nrender(<ForceMobileExample />);\n\n`,\n scope: [{\n name: \"_Navigation\",\n packageName: \"@components/Navigation\",\n component: component_95\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_96\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_97\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_100 from '@components/Permissions';\nimport * as component_101 from '@components/Global';\nimport * as component_102 from 'antd';\nconst readmeConfig = {\n name: `Permissions`,\n summary: `<h3>概述</h3>\n<p>Permissions 是一个权限控制组件,用于根据用户权限控制页面内容的显示。支持多种权限控制方式和展示形式,适用于各种需要权限控制的场景。</p>\n<h3>何时使用</h3>\n<p>在系统中存在一些功能和操作只允许某些角色用户使用,使用该组件可以让其包裹的组件或者区域根据系统的权限列表配置展示不同的状态</p>\n<h3>特点</h3>\n<p>通过在Global中的preset中设置permissions作为当前用户的权限列表,在Permissions组件配置permissions作为该功能要求具备的权限项,当要求具备的权限项全部在用户的权限列表中找到时为权限通过状态否则为权限不通过状态</p>\n<p>当权限不通过时,Permissions组件可以有三种方式呈现:</p>\n<ol>\n<li>用户可以看到操作功能的组件显示,但是不能进行操作,在鼠标移入时会以ToolTip提示错误原因,一般用在按钮等需要用户交互的功能位置</li>\n<li>用户不能看到操作功能或者数据呈现,对应区域显示错误原因,一般用在要数据展示等场景</li>\n<li>隐藏内部组件,一般用在不需要干扰到用户或用户不需要了解其没有权限的功能或数据等场景</li>\n</ol>\n<h3>高级特性</h3>\n<ul>\n<li>支持权限数组、权限函数和权限组合等多种权限验证方式</li>\n<li>提供权限判断的 Hook,方便在组件外部进行权限判断</li>\n<li>支持函数式子组件,可以获取权限验证结果并自定义渲染内容</li>\n</ul>`,\n \n \n api: `<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>type</td>\n<td>类型,可选值为hidden,tooltip,error,分别为隐藏,气泡提示,错误提示三种形式</td>\n<td>string</td>\n<td>hidden</td>\n</tr>\n<tr>\n<td>tagName</td>\n<td>当前组件的tagName,同React.createElement的type参数,默认为span</td>\n<td>string</td>\n<td>span</td>\n</tr>\n<tr>\n<td>message</td>\n<td>提示文案</td>\n<td>string</td>\n<td>您暂无权限,请联系管理员</td>\n</tr>\n<tr>\n<td>request</td>\n<td>权限列表可以为字符串数组、函数或混合类型,每个item为一项权限的key,所有权限在全局的permissions中存在则判断为权限通过</td>\n<td>array,function</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>children</td>\n<td>该参数可以传function类型,children({isPass, type, request}),isPass为权限校验是否通过,type为提示类型,request为所需权限列表,可以自行实现权限的展示</td>\n<td>jsx,function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>Hooks</h3>\n<h4>usePermissions</h4>\n<p>获取当前用户的权限列表</p>\n<pre><code class=\"language-javascript\">const { permissions } = usePermissions();\n</code></pre>\n<h4>usePermissionsPass</h4>\n<p>检查是否拥有指定权限</p>\n<pre><code class=\"language-javascript\">const isPass = usePermissionsPass({ request: ['user:view'] });\n</code></pre>\n<h3>工具函数</h3>\n<h4>computedIsPass</h4>\n<p>计算权限验证结果</p>\n<pre><code class=\"language-javascript\">const isPass = computedIsPass({ \n permissions: ['user:view', 'user:edit'], \n request: ['user:view'] \n});\n</code></pre>`,\n example: {\n isFull: false,\n className: `Permissions_d08cc`,\n style: `.Permissions_d08cc .box {\n padding: 20px;\n background: #f8f8f8;\n}`,\n list: [{\n title: `基础权限控制`,\n description: `展示Permissions组件的基本用法,包括不同类型的权限控制方式`,\n code: `const { default: Permissions } = _Permissions;\nconst { PureGlobal } = global;\nconst { Button, Radio, Space } = antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [type, setType] = useState(\"tooltip\");\n return (\n <PureGlobal\n preset={{\n permissions: [\"permission_1\", \"permission_2\"],\n }}\n >\n <Space direction=\"vertical\">\n <Radio.Group\n value={type}\n options={[\n { label: \"tooltip\", value: \"tooltip\" },\n {\n label: \"error\",\n value: \"error\",\n },\n { label: \"hidden\", value: \"hidden\" },\n ]}\n onChange={(e) => {\n setType(e.target.value);\n }}\n optionType=\"button\"\n buttonStyle=\"solid\"\n />\n <Permissions type={type} request={[\"permission_2\"]}>\n <div className=\"box\">\n <Button onClick={() => console.log(\"执行操作\")}>有权限操作</Button>\n </div>\n </Permissions>\n <Permissions type={type} request={[\"permission_3\"]}>\n <div className=\"box\">\n <Button onClick={() => console.log(\"执行操作\")}>无权限操作</Button>\n </div>\n </Permissions>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Permissions\",\n packageName: \"@components/Permissions\",\n component: component_100\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_101\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_102\n}]\n},{\n title: `高级权限控制`,\n description: `展示Permissions组件的高级用法,包括权限函数控制、多重权限控制和函数式子组件`,\n code: `const { default: Permissions } = _Permissions;\nconst { PureGlobal } = global;\nconst { Button, Card, Space, Table, Switch, Alert, Tag } = antd;\nconst { useState } = React;\n\n// 权限函数控制示例\nconst FunctionPermissionsExample = () => {\n const [userRole, setUserRole] = useState('user');\n \n const hasPermission = (permission) => {\n const rolePermissions = {\n admin: ['user:create', 'user:edit', 'user:delete', 'user:view', 'system:manage'],\n manager: ['user:create', 'user:edit', 'user:view', 'report:view'],\n user: ['user:view', 'profile:edit']\n };\n return rolePermissions[userRole] && rolePermissions[userRole].includes(permission);\n };\n \n const checkUserPermissions = (permissions) => {\n return permissions.some(p => hasPermission(p));\n };\n \n const roleSwitchItems = [\n { key: 'admin', label: '管理员' },\n { key: 'manager', label: '经理' },\n { key: 'user', label: '普通用户' },\n ];\n \n return (\n <Card title=\"权限函数控制\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Space>\n <span>用户角色:</span>\n <Button.Group>\n {roleSwitchItems.map(item => (\n <Button \n key={item.key}\n type={userRole === item.key ? 'primary' : 'default'}\n onClick={() => setUserRole(item.key)}\n >\n {item.label}\n </Button>\n ))}\n </Button.Group>\n </Space>\n \n <Alert \n message={\\`当前角色: \\${userRole === 'admin' ? '管理员' : userRole === 'manager' ? '经理' : '普通用户'}\\`}\n type=\"info\"\n />\n \n <Permissions \n request={['user:create']} \n type=\"hidden\"\n >\n <Button type=\"primary\">创建用户</Button>\n </Permissions>\n \n <Permissions \n request={checkUserPermissions} \n type=\"hidden\"\n >\n <Button>编辑用户</Button>\n </Permissions>\n \n <Permissions \n request={() => hasPermission('user:delete')} \n type=\"hidden\"\n >\n <Button danger>删除用户</Button>\n </Permissions>\n </Space>\n </Card>\n );\n};\n\n// 多重权限控制示例\nconst MultiplePermissionsExample = () => {\n const [permissions, setPermissions] = useState([\n 'user:view',\n 'order:view',\n 'product:view'\n ]);\n \n const permissionOptions = [\n { key: 'user:view', label: '查看用户' },\n { key: 'user:edit', label: '编辑用户' },\n { key: 'user:delete', label: '删除用户' },\n { key: 'order:view', label: '查看订单' },\n { key: 'order:edit', label: '编辑订单' },\n { key: 'product:view', label: '查看产品' },\n { key: 'product:edit', label: '编辑产品' },\n { key: 'system:manage', label: '系统管理' },\n ];\n \n const togglePermission = (permission) => {\n setPermissions(prev => \n prev.includes(permission) \n ? prev.filter(p => p !== permission)\n : [...prev, permission]\n );\n };\n \n return (\n <Card title=\"多重权限控制\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <span>当前权限: </span>\n <Space wrap>\n {permissionOptions.map(option => (\n <Tag \n key={option.key}\n color={permissions.includes(option.key) ? 'blue' : 'default'}\n onClick={() => togglePermission(option.key)}\n style={{ cursor: 'pointer' }}\n >\n {option.label}\n </Tag>\n ))}\n </Space>\n </div>\n \n <Space wrap>\n <Permissions \n request={['user:view', 'user:edit']} \n type=\"hidden\"\n >\n <Button>用户管理</Button>\n </Permissions>\n \n <Permissions \n request={['order:view', 'order:edit']} \n type=\"hidden\"\n >\n <Button>订单管理</Button>\n </Permissions>\n \n <Permissions \n request={['product:view', 'product:edit']} \n type=\"hidden\"\n >\n <Button>产品管理</Button>\n </Permissions>\n \n <Permissions \n request={['system:manage']} \n type=\"hidden\"\n >\n <Button type=\"primary\" danger>系统管理</Button>\n </Permissions>\n </Space>\n </Space>\n </Card>\n );\n};\n\n// 函数式子组件示例\nconst FunctionChildrenExample = () => {\n const [permissions] = useState(['user:view', 'order:view']);\n \n return (\n <Card title=\"函数式子组件\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <Alert \n message=\"函数式子组件允许根据权限状态自定义渲染内容\"\n type=\"info\"\n />\n \n <Permissions \n request={['user:view']} \n type=\"hidden\"\n >\n {({ isPass, type, request }) => (\n <div>\n <p>权限状态: {isPass ? '有权限' : '无权限'}</p>\n <p>权限类型: {type}</p>\n <p>所需权限: {request.join(', ')}</p>\n <Button type={isPass ? 'primary' : 'default'} disabled={!isPass}>\n {isPass ? '可以访问用户页面' : '无权访问用户页面'}\n </Button>\n </div>\n )}\n </Permissions>\n \n <Permissions \n request={['order:view']} \n type=\"tooltip\"\n message=\"您没有查看订单的权限\"\n >\n {({ isPass }) => (\n <div>\n <Button type={isPass ? 'primary' : 'default'}>\n {isPass ? '查看订单' : '查看订单(无权限)'}\n </Button>\n </div>\n )}\n </Permissions>\n </Space>\n </Card>\n );\n};\n\n// 权限表格控制示例\nconst TablePermissionsExample = () => {\n const [permissions] = useState(['user:view', 'user:edit']);\n const [permissionType, setPermissionType] = useState('hidden');\n \n const columns = [\n {\n title: '姓名',\n dataIndex: 'name',\n key: 'name',\n },\n {\n title: '邮箱',\n dataIndex: 'email',\n key: 'email',\n },\n {\n title: '操作',\n key: 'action',\n render: (_, record) => (\n <Space size=\"middle\">\n <Permissions \n request={['user:edit']} \n type={permissionType}\n >\n <Button type=\"link\" size=\"small\">编辑</Button>\n </Permissions>\n <Permissions \n request={['user:delete']} \n type={permissionType}\n >\n <Button type=\"link\" size=\"small\" danger>删除</Button>\n </Permissions>\n </Space>\n ),\n },\n ];\n \n const data = [\n {\n key: '1',\n name: '张三',\n email: 'zhangsan@example.com',\n },\n {\n key: '2',\n name: '李四',\n email: 'lisi@example.com',\n },\n {\n key: '3',\n name: '王五',\n email: 'wangwu@example.com',\n },\n ];\n \n return (\n <Card title=\"权限表格控制\" size=\"small\">\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <div>\n <span>权限类型: </span>\n <Switch \n checked={permissionType === 'hidden'}\n onChange={(checked) => setPermissionType(checked ? 'hidden' : 'tooltip')}\n />\n <span>{permissionType === 'hidden' ? '隐藏' : '提示'}</span>\n </div>\n \n <Table columns={columns} dataSource={data} pagination={false} />\n </Space>\n </Card>\n );\n};\n\nconst AdvancedPermissionsExample = () => {\n return (\n <Space direction=\"vertical\" style={{ width: '100%' }}>\n <FunctionPermissionsExample />\n <MultiplePermissionsExample />\n <FunctionChildrenExample />\n <TablePermissionsExample />\n </Space>\n );\n};\n\nrender(<AdvancedPermissionsExample />);\n`,\n scope: [{\n name: \"_Permissions\",\n packageName: \"@components/Permissions\",\n component: component_100\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_101\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_102\n}]\n},{\n title: `Hooks使用`,\n description: `展示Permissions组件的Hooks使用,包括usePermissions、usePermissionsPass和computedIsPass工具函数`,\n code: `const { default: Permissions, usePermissions, usePermissionsPass, computedIsPass } = _Permissions;\nconst { PureGlobal } = global;\nconst { Card, Space, Tag, Typography } = antd;\n\nconst PermissionsInfo = () => {\n const { permissions } = usePermissions();\n const hasUserPermission = usePermissionsPass({ request: [\"user:view\"] });\n const hasOrderPermission = usePermissionsPass({ request: [\"order:view\"] });\n \n const manualCheck = computedIsPass({\n permissions,\n request: [\"user:edit\", \"user:delete\"]\n });\n\n return (\n <Card title=\"权限信息展示\" style={{ width: 600 }}>\n <Space direction=\"vertical\" style={{ width: \"100%\" }}>\n <div>\n <Typography.Text strong>当前用户权限列表: </Typography.Text>\n <Space wrap>\n {permissions.map((perm) => (\n <Tag key={perm} color=\"blue\">{perm}</Tag>\n ))}\n </Space>\n </div>\n \n <div>\n <Typography.Text strong>用户查看权限: </Typography.Text>\n <Tag color={hasUserPermission ? \"green\" : \"red\"}>\n {hasUserPermission ? \"有权限\" : \"无权限\"}\n </Tag>\n </div>\n \n <div>\n <Typography.Text strong>订单查看权限: </Typography.Text>\n <Tag color={hasOrderPermission ? \"green\" : \"red\"}>\n {hasOrderPermission ? \"有权限\" : \"无权限\"}\n </Tag>\n </div>\n \n <div>\n <Typography.Text strong>手动权限检查(用户编辑/删除): </Typography.Text>\n <Tag color={manualCheck ? \"green\" : \"red\"}>\n {manualCheck ? \"有权限\" : \"无权限\"}\n </Tag>\n </div>\n </Space>\n </Card>\n );\n};\n\nconst HooksUsageExample = () => {\n return (\n <PureGlobal\n preset={{\n permissions: [\"user:view\", \"user:edit\", \"dashboard:view\", \"report:view\"],\n }}\n >\n <Space direction=\"vertical\" size=\"large\">\n <PermissionsInfo />\n \n <Permissions request={[\"user:view\"]} type=\"tooltip\">\n <Card title=\"用户信息\" style={{ width: 600 }}>\n <Space direction=\"vertical\">\n <div>用户名: 张三</div>\n <div>部门: 技术部</div>\n <div>职位: 前端开发工程师</div>\n </Space>\n </Card>\n </Permissions>\n \n <Permissions request={[\"order:view\"]} type=\"error\" message=\"您没有订单查看权限,请联系部门管理员\">\n <Card title=\"订单信息\" style={{ width: 600 }}>\n <div>订单列表内容...</div>\n </Card>\n </Permissions>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<HooksUsageExample />);\n\n`,\n scope: [{\n name: \"_Permissions\",\n packageName: \"@components/Permissions\",\n component: component_100\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_101\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_102\n}]\n},{\n title: `自定义标签`,\n description: `展示Permissions组件的tagName属性,使用不同的HTML标签包裹无权限内容`,\n code: `const { default: Permissions } = _Permissions;\nconst { PureGlobal } = global;\nconst { Space, Button } = antd;\n\nconst CustomTagExample = () => {\n return (\n <PureGlobal\n preset={{\n permissions: [\"document:view\", \"document:edit\"],\n }}\n >\n <Space direction=\"vertical\">\n <div>\n <h4>默认 span 标签:</h4>\n <Permissions request={[\"document:view\"]} type=\"tooltip\">\n <Button>查看文档</Button>\n </Permissions>\n </div>\n \n <div>\n <h4>自定义 div 标签:</h4>\n <Permissions\n request={[\"document:delete\"]}\n type=\"tooltip\"\n tagName=\"div\"\n className=\"permission-wrapper\"\n >\n <Button danger>删除文档(无权限)</Button>\n </Permissions>\n </div>\n \n <div>\n <h4>自定义 section 标签:</h4>\n <Permissions\n request={[\"document:edit\"]}\n type=\"tooltip\"\n tagName=\"section\"\n className=\"permission-section\"\n >\n <Button type=\"primary\">编辑文档</Button>\n </Permissions>\n </div>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<CustomTagExample />);\n\n`,\n scope: [{\n name: \"_Permissions\",\n packageName: \"@components/Permissions\",\n component: component_100\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_101\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_102\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_98 from '@components/StateBar';\nimport * as component_99 from 'antd';\nconst readmeConfig = {\n name: `StateBar`,\n summary: `<h3>概述</h3>\n<p>StateBar 是一个基于 Ant Design Tabs 组件的状态栏组件,支持多种展示类型(tab、radio、step),适用于需要状态切换和流程展示的场景。</p>\n<h3>何时使用</h3>\n<p>当需要在页面中展示不同状态的选项卡或步骤流程时使用,例如:</p>\n<ul>\n<li>数据列表的状态筛选(全部、待处理、已完成等)</li>\n<li>表单或流程的步骤展示</li>\n<li>选项卡切换界面</li>\n</ul>\n<h3>特点</h3>\n<ul>\n<li>支持三种展示类型:tab(标签页)、radio(单选)、step(步骤)</li>\n<li>可自定义样式和尺寸(small、default、large)</li>\n<li>支持底部线条延展效果(isInner 属性)</li>\n<li>可添加额外内容在状态栏右侧</li>\n<li>基于 Ant Design Tabs,兼容其大部分属性</li>\n</ul>`,\n \n \n api: `<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>stateOption</td>\n<td>state操作列表</td>\n<td>string</td>\n<td>{key: string, tab: ReactNode}[]</td>\n</tr>\n<tr>\n<td>activeKey</td>\n<td>当前激活 tab 面板的 key</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>type</td>\n<td>当前tab展示样式</td>\n<td>'tab'、'radio'、'step'</td>\n<td>'tab'</td>\n</tr>\n<tr>\n<td>onChange</td>\n<td>事件返回选中的key</td>\n<td>(value: string) => void</td>\n<td></td>\n</tr>\n<tr>\n<td>tabBarExtraContent</td>\n<td>展示在state bar右侧</td>\n<td>ReactNode</td>\n<td>null</td>\n</tr>\n<tr>\n<td>isInner</td>\n<td>底部线延展至总长</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<h3>Mapping</h3>\n<h4>stateOption</h4>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>key</td>\n<td>对应 activeKey</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>tab</td>\n<td>选项卡头显示文字</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础状态栏`,\n description: `展示StateBar组件的基础用法,包括不同类型和尺寸的配置`,\n code: `const { default: StateBar } = _StateBar;\nconst { Button, Radio, Space } = antd;\nconst { useState } = React;\n\nconst BaseExample = () => {\n const [size, setSize] = useState(\"default\");\n const [isInner, setIsInner] = useState(false);\n return (\n <Space direction=\"vertical\">\n <Radio.Group\n value={isInner}\n options={[\n { label: \"inner\", value: true },\n { label: \"normal\", value: false },\n ]}\n onChange={(e) => {\n setIsInner(e.target.value);\n }}\n optionType=\"button\"\n buttonStyle=\"solid\"\n />\n <Radio.Group\n value={size}\n options={[\n { label: \"small\", value: \"small\" },\n { label: \"default\", value: \"default\" },\n { label: \"large\", value: \"large\" },\n ]}\n onChange={(e) => {\n setSize(e.target.value);\n }}\n optionType=\"button\"\n buttonStyle=\"solid\"\n />\n <StateBar\n size={size}\n isInner={isInner}\n stateOption={[\n { tab: \"全部\", key: \"1\" },\n { tab: \"科目一\", key: \"2\" },\n {\n tab: \"科目二\",\n key: \"3\",\n },\n { tab: \"科目三\", key: \"4\" },\n { tab: \"科目四\", key: \"5\" },\n ]}\n />\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateBar\",\n packageName: \"@components/StateBar\",\n component: component_98\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_99\n}]\n},{\n title: `Radio类型状态栏`,\n description: `展示StateBar组件的radio类型,适合选项较多的场景`,\n code: `const { default: StateBar } = _StateBar;\nconst { Radio, Space } = antd;\nconst { useState } = React;\n\nconst BaseStateExample = () => {\n const [size, setSize] = useState(\"default\");\n return (\n <Space direction=\"vertical\">\n <Radio.Group\n value={size}\n options={[\n { label: \"small\", value: \"small\" },\n { label: \"default\", value: \"default\" },\n { label: \"large\", value: \"large\" },\n ]}\n onChange={(e) => {\n setSize(e.target.value);\n }}\n optionType=\"button\"\n buttonStyle=\"solid\"\n />\n <StateBar\n size={size}\n type=\"radio\"\n stateOption={[\n { tab: \"全部\", key: \"1\" },\n { tab: \"科目一\", key: \"2\" },\n { tab: \"科目二\", key: \"3\" },\n { tab: \"科目三\", key: \"4\" },\n { tab: \"科目四\", key: \"5\" },\n { tab: \"科目一1\", key: \"22\" },\n { tab: \"科目二2\", key: \"33\" },\n { tab: \"科目三3\", key: \"44\" },\n { tab: \"科目四4\", key: \"55\", style: { cursor: \"copy\" } },\n ]}\n />\n </Space>\n );\n};\n\nrender(<BaseStateExample />);\n\n`,\n scope: [{\n name: \"_StateBar\",\n packageName: \"@components/StateBar\",\n component: component_98\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_99\n}]\n},{\n title: `Step类型状态栏`,\n description: `展示StateBar组件的step类型,适合展示流程步骤`,\n code: `const { default: StateBar } = _StateBar;\n\nconst BaseStateExample = () => {\n return (\n <StateBar\n type=\"step\"\n stateOption={[\n { tab: \"全部\", key: \"1\" },\n { tab: \"科目一\", key: \"2\" },\n { tab: \"科目二\", key: \"3\" },\n { tab: \"科目三\", key: \"4\" },\n { tab: \"科目四\", key: \"5\" },\n { tab: \"科目一1\", key: \"22\" },\n { tab: \"科目二2\", key: \"33\" },\n { tab: \"科目三3\", key: \"44\" },\n { tab: \"科目四4\", key: \"55\", className: \"last\" },\n ]}\n tabBarExtraContent={<div>测试</div>}\n />\n );\n};\n\nrender(<BaseStateExample />);\n\n`,\n scope: [{\n name: \"_StateBar\",\n packageName: \"@components/StateBar\",\n component: component_98\n}]\n},{\n title: `受控模式`,\n description: `展示StateBar组件的受控模式,包括activeKey和onChange事件的使用`,\n code: `const { default: StateBar } = _StateBar;\nconst { Button, Card, Space, Tag } = antd;\nconst { useState } = React;\n\nconst ControlledModeExample = () => {\n const [activeKey, setActiveKey] = useState(\"1\");\n \n const stateOption = [\n { key: \"1\", tab: \"待处理\" },\n { key: \"2\", tab: \"处理中\" },\n { key: \"3\", tab: \"待审核\" },\n { key: \"4\", tab: \"已完成\" },\n { key: \"5\", tab: \"已拒绝\" },\n ];\n \n const statusData = {\n \"1\": { count: 15, color: \"orange\", description: \"等待处理的工单\" },\n \"2\": { count: 8, color: \"blue\", description: \"正在处理的工单\" },\n \"3\": { count: 5, color: \"purple\", description: \"等待审核的工单\" },\n \"4\": { count: 128, color: \"green\", description: \"已完成的工单\" },\n \"5\": { count: 3, color: \"red\", description: \"已拒绝的工单\" },\n };\n\n const handleTabChange = (key) => {\n setActiveKey(key);\n };\n\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <Card title=\"工单状态管理\" style={{ width: \"100%\" }}>\n <StateBar\n type=\"tab\"\n activeKey={activeKey}\n stateOption={stateOption}\n onChange={handleTabChange}\n tabBarExtraContent={\n <Button type=\"primary\" size=\"small\">\n 新建工单\n </Button>\n }\n />\n \n <Card style={{ marginTop: 20 }}>\n <Space direction=\"vertical\" size=\"middle\">\n <div>\n <Tag color={statusData[activeKey].color}>\n {stateOption.find(item => item.key === activeKey)?.tab}\n </Tag>\n <span style={{ marginLeft: 8 }}>数量: {statusData[activeKey].count} 个</span>\n </div>\n <div>\n <strong>状态描述:</strong> {statusData[activeKey].description}\n </div>\n <div>\n <strong>当前选中:</strong> {activeKey}\n </div>\n </Space>\n </Card>\n </Card>\n \n <Card title=\"快速切换\" style={{ width: \"100%\" }}>\n <Space wrap>\n {stateOption.map(item => (\n <Button\n key={item.key}\n onClick={() => setActiveKey(item.key)}\n type={activeKey === item.key ? \"primary\" : \"default\"}\n >\n 切换到: {item.tab}\n </Button>\n ))}\n </Space>\n </Card>\n </Space>\n );\n};\n\nrender(<ControlledModeExample />);\n\n`,\n scope: [{\n name: \"_StateBar\",\n packageName: \"@components/StateBar\",\n component: component_98\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_99\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_103 from '@components/StateTag';\nimport * as component_104 from '@components/Descriptions';\nimport * as component_105 from 'lodash';\nimport * as component_106 from 'antd';\nimport * as component_107 from '@components/Global';\nconst readmeConfig = {\n name: `StateTag`,\n summary: `<h3>概述</h3>\n<p>StateTag 是一个状态标签组件,用于展示不同状态的数据。支持多种预设类型和自定义样式,适用于列表、详情页等场景的状态展示。</p>\n<h3>何时使用</h3>\n<p>当需要展示数据的状态时使用,例如:</p>\n<ul>\n<li>列表页表格中的状态列</li>\n<li>详情页中的状态信息</li>\n<li>筛选结果展示</li>\n<li>技能标签展示</li>\n</ul>\n<h3>特点</h3>\n<ul>\n<li>提供多种预设状态类型(info、success、progress、danger、default 等)</li>\n<li>支持自定义边框和背景色</li>\n<li>支持筛选结果标签(filterResult 类型)</li>\n<li>可显示前置筛选名称(filterName 属性)</li>\n<li>基于 Ant Design Tag,兼容其大部分属性</li>\n</ul>\n<h3>使用场景</h3>\n<ul>\n<li><strong>info</strong>(蓝色 #155ACF):待处理、待审核等状态</li>\n<li><strong>progress</strong>(橙色 #F09700):进行中、审核中等状态</li>\n<li><strong>success</strong>(绿色 #027A48):已完成、已通过等状态</li>\n<li><strong>danger</strong>(红色 #D14343):失败、拒绝、异常等状态</li>\n<li><strong>default</strong>(灰色 #666666):已取消、已关闭等状态</li>\n<li><strong>filterResult</strong>(青色 #5CB8B2):筛选结果标签</li>\n<li><strong>skill</strong>(灰色 #666666):技能标签,带特殊边框</li>\n<li><strong>result</strong>(灰色 #666666):下拉菜单、弹窗中的已选结果标签</li>\n</ul>`,\n \n \n api: `<h3>StateTag 属性</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>type</td>\n<td>tag的类型,类型决定显示的颜色</td>\n<td>'default'(#666666)、'skill'(#666666)(此时边框颜色为 #EEEEEE)、'success'(#027A48)、'progress'(#F09700)、'danger'(#D14343)、'info'(#155ACF)、'other'(#6740C3)(待定颜色)、'result'(#666666)、'filterResult'(#5CB8B2)</td>\n<td>'default'</td>\n</tr>\n<tr>\n<td>showBorder</td>\n<td>是否展示边框</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>showBackground</td>\n<td>是否展示背景色</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>text</td>\n<td>tag文案</td>\n<td>string</td>\n<td>''</td>\n</tr>\n<tr>\n<td>filterName</td>\n<td>tag类型为\"filterResult\"时显示在前边的文案</td>\n<td>string</td>\n<td>''</td>\n</tr>\n</tbody>\n</table>\n<p>其他参数参考 <a href=\"https://ant.design/components/tag-cn\">antd Tag.Tag</a></p>\n<h3>StateTagEnum 属性</h3>\n<p>StateTagEnum 是基于 Enum 组件和 StateTag 组件的封装,用于从枚举数据中自动获取状态标签。</p>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>moduleName</td>\n<td>枚举模块名称</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>name</td>\n<td>枚举项名称</td>\n<td>string</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<p>其他属性继承自 StateTag 组件</p>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `基本示例`,\n description: `状态标签`,\n code: `const { default: StateTag } = _StateTag;\nconst { default: Descriptions } = _Descriptions;\nconst { range } = lodash;\nconst { Space, Typography } = antd;\n\nconst BaseExample = () => {\n return (\n <div>\n <div>使用场景: 列表页Table,简历详情页</div>\n <br />\n <Descriptions\n dataSource={[\n [\n { label: \"使用规则\", content: \"待XX,暂停\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"info\", text: \"待提交开票\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"info\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"XX中,正在XX中\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"progress\", text: \"退票审核中\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"progress\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"通过,成功,完成\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"success\", text: \"标签内容\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"success\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"不通过,失败,淘汰,缺席,拒绝\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"danger\", text: \"退票拒绝\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"danger\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"取消,撤销,停止\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"default\", text: \"撤销开票审核\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"default\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"(暂时还未用到)\" },\n {\n label: \"示例\",\n content: (\n <Space>\n <StateTag {...{ type: \"other\", text: \"标签内容\" }} />\n <Typography.Text\n copyable={{\n text: '<StateTag type=\"other\" text=\"标签内容\" />',\n }}\n />\n </Space>\n ),\n },\n ],\n ]}\n />\n <br />\n <br />\n <div>个别特殊场景(需要单独询问UI):</div>\n <br />\n <Descriptions\n dataSource={[\n [\n { label: \"使用规则\", content: \"待XX,暂停\" },\n {\n label: \"示例\",\n content: (\n <div>\n <StateTag {...{ type: \"success\", text: \"已推荐简历\" }} />\n <StateTag {...{ type: \"success\", text: \"已退票\" }} />\n </div>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"已XX待XX\" },\n {\n label: \"示例\",\n content: (\n <div>\n <StateTag {...{ type: \"success\", text: \"已开票待寄出\" }} />\n <StateTag {...{ type: \"success\", text: \"已待寄待收款\" }} />\n </div>\n ),\n },\n ],\n [\n {\n label: \"使用规则\",\n content: \"已XX+词语:根据后面的词语语义进行判断\",\n },\n {\n label: \"示例\",\n content: (\n <div>\n <StateTag {...{ type: \"success\", text: \"已成功\" }} />\n <StateTag {...{ type: \"default\", text: \"已取消\" }} />\n <StateTag {...{ type: \"danger\", text: \"已失败\" }} />\n <StateTag {...{ type: \"progress\", text: \"已暂停\" }} />\n </div>\n ),\n },\n ],\n [\n { label: \"使用规则\", content: \"完全根据语义语境判断\" },\n {\n label: \"示例\",\n content: (\n <div>\n <StateTag {...{ type: \"success\", text: \"全部到款\" }} />\n <StateTag {...{ type: \"success\", text: \"部分到款\" }} />\n <StateTag {...{ type: \"success\", text: \"简历亮点\" }} />\n <StateTag {...{ type: \"danger\", text: \"简历风险点\" }} />\n </div>\n ),\n },\n ],\n ]}\n />\n </div>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n},{\n name: \"_Descriptions\",\n packageName: \"@components/Descriptions\",\n component: component_104\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_105\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_106\n}]\n},{\n title: `技能标签示例`,\n description: `展示技能标签的使用,包括边框和背景的配置`,\n code: `const { default: StateTag } = _StateTag;\n\nconst BaseExample = () => {\n return (\n <div>\n <StateTag\n text={\"技能标签\"}\n type={\"skill\"}\n showBorder\n showBackground={false}\n />\n </div>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n}]\n},{\n title: `结果标签示例`,\n description: `展示下拉菜单、弹窗中已选结果标签的使用`,\n code: `const { default: StateTag } = _StateTag;\n\nconst BaseExample = () => {\n return (\n <div>\n <StateTag\n text={\"技能标签\"}\n type={\"result\"}\n showBackground={false}\n closable\n onClose={() => console.log(\"close\")}\n />\n <StateTag\n text={\"技能标签\"}\n type={\"result\"}\n closable\n onClose={() => console.log(\"close\")}\n />\n </div>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n}]\n},{\n title: `筛选结果标签`,\n description: `展示筛选组件中筛选结果标签的使用,包括filterName属性`,\n code: `const { default: StateTag } = _StateTag;\n\nconst BaseExample = () => {\n return (\n <div>\n <StateTag\n filterName={\"BD\"}\n text={\"陈枫林,王晓晨\"}\n type={\"filterResult\"}\n closable\n onClose={() => console.log(\"close\")}\n />\n <br />\n <StateTag\n filterName={\"添加人\"}\n text={\"陈枫林,王晓晨,陈路,张力\"}\n type={\"filterResult\"}\n closable\n onClose={() => console.log(\"close\")}\n />\n </div>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n}]\n},{\n title: `枚举状态标签`,\n description: `展示StateTagEnum组件的使用,从枚举数据自动生成状态标签`,\n code: `const { StateTagEnum } = _StateTag;\nconst { PureGlobal } = global;\nconst { Space } = antd;\n\nconst BaseExample = ()=>{\n return (\n <PureGlobal\n preset={{\n locale: \"zh-CN\",\n enums: {\n testEnums: async ({ locale }) => {\n console.log(locale);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve([\n { value: \"1\", description: \"第一项\", type: 'success' },\n { value: \"2\", description: \"第二项\", type: 'danger' },\n { value: \"3\", description: \"第三项\", type: 'info'},\n ]);\n }, 1000);\n });\n },\n },\n }}\n >\n <Space>\n <StateTagEnum moduleName=\"testEnums\" name=\"1\" />\n <StateTagEnum moduleName=\"testEnums\" name=\"2\" />\n <StateTagEnum moduleName=\"testEnums\" name=\"3\" />\n </Space>\n </PureGlobal>\n )\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_106\n},{\n name: \"global\",\n packageName: \"@components/Global\",\n component: component_107\n}]\n},{\n title: `边框背景组合`,\n description: `展示StateTag组件不同type下showBorder和showBackground属性的组合效果,以及Antd Tag的其他属性`,\n code: `const { default: StateTag } = _StateTag;\nconst { Card, Divider, Space, Table, message } = antd;\n\nconst BorderBgCombinationsExample = () => {\n const types = [\n { key: \"default\", label: \"默认\", business: \"已取消/已关闭\" },\n { key: \"skill\", label: \"技能\", business: \"技能标签\" },\n { key: \"result\", label: \"结果\", business: \"筛选结果\" },\n { key: \"filterResult\", label: \"筛选结果\", business: \"筛选条件\" },\n { key: \"success\", label: \"成功\", business: \"已通过/已完成\" },\n { key: \"progress\", label: \"进行中\", business: \"审核中/处理中\" },\n { key: \"danger\", label: \"危险\", business: \"已拒绝/已失败\" },\n { key: \"info\", label: \"信息\", business: \"待处理/待审核\" },\n { key: \"other\", label: \"其他\", business: \"其他状态\" },\n ];\n\n const columns = [\n {\n title: \"状态类型\",\n dataIndex: \"type\",\n render: (_, record) => (\n <Space>\n <StateTag text={record.label} type={record.key} />\n <span>{record.label}</span>\n </Space>\n ),\n },\n {\n title: \"无边框有背景(默认)\",\n dataIndex: \"noBorder\",\n render: (_, record) => (\n <StateTag \n text={record.business} \n type={record.key} \n showBorder={false} \n showBackground={true} \n />\n ),\n },\n {\n title: \"有边框有背景\",\n dataIndex: \"withBorder\",\n render: (_, record) => (\n <StateTag \n text={record.business} \n type={record.key} \n showBorder={true} \n showBackground={true} \n />\n ),\n },\n {\n title: \"有边框无背景\",\n dataIndex: \"borderNoBg\",\n render: (_, record) => (\n <StateTag \n text={record.business} \n type={record.key} \n showBorder={true} \n showBackground={false} \n />\n ),\n },\n {\n title: \"业务场景示例\",\n dataIndex: \"businessExample\",\n render: (_, record) => {\n const examples = {\n default: \"已取消开票\",\n skill: \"React, Vue, JavaScript\",\n result: \"已选择: 5项\",\n filterResult: \"BD: 张三, 李四\",\n success: \"审核已通过\",\n progress: \"审核进行中\",\n danger: \"审核已拒绝\",\n info: \"待提交审核\",\n other: \"其他状态标签\",\n };\n return (\n <StateTag \n text={examples[record.key]} \n type={record.key} \n filterName={record.key === \"filterResult\" ? \"BD\" : undefined}\n />\n );\n },\n },\n ];\n\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <Card title=\"状态标签边框与背景组合效果\">\n <p>展示不同状态下边框和背景的组合效果,帮助选择最适合业务场景的配置。</p>\n <Table\n columns={columns}\n dataSource={types}\n rowKey=\"key\"\n pagination={false}\n bordered\n />\n </Card>\n \n <Divider />\n \n <Card title=\"Ant Design Tag 其他属性展示\">\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <h4>可关闭标签:</h4>\n <Space wrap>\n <StateTag \n text=\"可关闭的成功标签\" \n type=\"success\" \n closable \n onClose={() => console.log(\"关闭了成功标签\")}\n />\n <StateTag \n text=\"可关闭的筛选结果\" \n type=\"filterResult\" \n filterName=\"部门\"\n closable \n onClose={() => console.log(\"关闭了筛选结果\")}\n />\n </Space>\n </div>\n \n <div>\n <h4>可点击标签(带事件):</h4>\n <Space wrap>\n <StateTag \n text=\"点击查看详情\" \n type=\"info\" \n onClick={() => message.info(\"点击了信息标签\")}\n style={{ cursor: \"pointer\" }}\n />\n <StateTag \n text=\"查看进度\" \n type=\"progress\" \n onClick={() => message.info(\"点击了进度标签\")}\n style={{ cursor: \"pointer\" }}\n />\n </Space>\n </div>\n \n <div>\n <h4>自定义样式:</h4>\n <Space wrap>\n <StateTag \n text=\"圆角标签\" \n type=\"success\" \n style={{ borderRadius: 20 }}\n />\n <StateTag \n text=\"大字号标签\" \n type=\"danger\" \n style={{ fontSize: 16, padding: \"4px 12px\" }}\n />\n </Space>\n </div>\n </Space>\n </Card>\n \n <Card title=\"实际业务场景示例\">\n <Space direction=\"vertical\" size=\"middle\" style={{ width: \"100%\" }}>\n <div>\n <strong>项目状态:</strong>\n <Space>\n <StateTag text=\"项目立项\" type=\"info\" />\n <StateTag text=\"开发中\" type=\"progress\" />\n <StateTag text=\"测试阶段\" type=\"progress\" />\n <StateTag text=\"已上线\" type=\"success\" />\n <StateTag text=\"已暂停\" type=\"default\" />\n </Space>\n </div>\n \n <div>\n <strong>审批流程:</strong>\n <Space>\n <StateTag text=\"待提交\" type=\"info\" />\n <StateTag text=\"部门审核中\" type=\"progress\" />\n <StateTag text=\"财务审核中\" type=\"progress\" />\n <StateTag text=\"总经理审批中\" type=\"progress\" />\n <StateTag text=\"已通过\" type=\"success\" />\n <StateTag text=\"已拒绝\" type=\"danger\" />\n </Space>\n </div>\n \n <div>\n <strong>筛选条件:</strong>\n <Space>\n <StateTag text=\"北京分公司, 上海分公司\" type=\"filterResult\" filterName=\"分公司\" />\n <StateTag text=\"技术部, 产品部\" type=\"filterResult\" filterName=\"部门\" />\n <StateTag text=\"2024-01-01 至 2024-12-31\" type=\"filterResult\" filterName=\"日期范围\" />\n </Space>\n </div>\n \n <div>\n <strong>技能标签:</strong>\n <Space>\n <StateTag text=\"React\" type=\"skill\" showBorder showBackground={false} />\n <StateTag text=\"Vue.js\" type=\"skill\" showBorder showBackground={false} />\n <StateTag text=\"JavaScript\" type=\"skill\" showBorder showBackground={false} />\n <StateTag text=\"TypeScript\" type=\"skill\" showBorder showBackground={false} />\n <StateTag text=\"Node.js\" type=\"skill\" showBorder showBackground={false} />\n </Space>\n </div>\n </Space>\n </Card>\n </Space>\n );\n};\n\nrender(<BorderBgCombinationsExample />);\n\n`,\n scope: [{\n name: \"_StateTag\",\n packageName: \"@components/StateTag\",\n component: component_103\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_106\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_108 from '@components/Table';\nimport * as component_109 from '@components/Global';\nimport * as component_110 from '@kne/react-fetch';\nimport * as component_111 from 'antd';\nimport * as component_112 from 'lodash';\nconst readmeConfig = {\n name: `Table`,\n summary: `<p>Table 组件是一个功能强大的数据表格组件,基于 Ant Design Table 二次封装,提供了丰富的列类型、列配置、排序、分组表头、操作列等高级功能。</p>\n<p>组件支持两种使用方式:</p>\n<ul>\n<li><strong>Table</strong>: 基础表格组件,适用于静态数据展示</li>\n<li><strong>TablePage</strong>: 集成数据加载、分页、权限控制的完整表格解决方案</li>\n</ul>\n<p>主要特性:</p>\n<ul>\n<li>内置 16+ 种列类型(日期、编号、用户、标签、头像等)</li>\n<li>支持列拖拽调整宽度、列显示/隐藏、列排序</li>\n<li>支持分组表头</li>\n<li>支持行选择(checkbox)</li>\n<li>支持操作列(options)</li>\n<li>支持本地存储列配置</li>\n<li>支持自定义列渲染</li>\n</ul>`,\n \n \n api: `<h3>Table 组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>columns</td>\n<td>列配置</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>getScrollEl</td>\n<td>获取滚动容器</td>\n<td>function</td>\n<td>getScrollElDefault</td>\n</tr>\n<tr>\n<td>sticky</td>\n<td>是否固定表头</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>stickyOffset</td>\n<td>固定表头偏移量</td>\n<td>string</td>\n<td>\"var(--nav-height)\"</td>\n</tr>\n<tr>\n<td>pagination</td>\n<td>分页配置</td>\n<td>boolean/object</td>\n<td>false</td>\n</tr>\n<tr>\n<td>columnRenderProps</td>\n<td>列渲染属性</td>\n<td>object</td>\n<td>{}</td>\n</tr>\n<tr>\n<td>rowKey</td>\n<td>行key</td>\n<td>string/function</td>\n<td>\"id\"</td>\n</tr>\n<tr>\n<td>dataSource</td>\n<td>数据源</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>controllerOpen</td>\n<td>是否开启列控制</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>name</td>\n<td>表格名称(用于存储配置)</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>summary</td>\n<td>总结栏</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>scroll</td>\n<td>滚动配置</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>scroller</td>\n<td>滚动器配置</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onTablePropsReady</td>\n<td>表格属性就绪回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TablePage 组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>loader</td>\n<td>数据加载函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>featureId</td>\n<td>功能ID(用于权限控制)</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>pagination</td>\n<td>分页配置</td>\n<td>object</td>\n<td>{open: true, ...}</td>\n</tr>\n<tr>\n<td>name</td>\n<td>表格名称</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>dataFormat</td>\n<td>数据格式化函数</td>\n<td>function</td>\n<td>(data) => ({list, total})</td>\n</tr>\n<tr>\n<td>className</td>\n<td>自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>columnRenderProps</td>\n<td>列渲染属性</td>\n<td>object</td>\n<td>{}</td>\n</tr>\n<tr>\n<td>summary</td>\n<td>总结栏</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>sticky</td>\n<td>是否固定表头</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>columns</td>\n<td>列配置</td>\n<td>array/function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>getColumns</td>\n<td>获取列配置的函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>useSelectedRow Hook</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>options.rowKey</td>\n<td>行key</td>\n<td>string/function</td>\n<td>'id'</td>\n</tr>\n<tr>\n<td>selectedRowKeys</td>\n<td>选中行的keys</td>\n<td>array</td>\n<td>[]</td>\n</tr>\n<tr>\n<td>onSelectAll</td>\n<td>全选回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>onSelect</td>\n<td>单选回调</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>setSelectedRowKeys</td>\n<td>设置选中行</td>\n<td>function</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>列配置(Column)</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>列名称(唯一标识)</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>列标题</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>type</td>\n<td>列类型</td>\n<td>string</td>\n<td>'other'</td>\n</tr>\n<tr>\n<td>width</td>\n<td>列宽度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>min</td>\n<td>最小宽度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>max</td>\n<td>最大宽度</td>\n<td>number</td>\n<td>-</td>\n</tr>\n<tr>\n<td>hidden</td>\n<td>是否隐藏</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>fixed</td>\n<td>固定列</td>\n<td>'left'/'right'</td>\n<td>-</td>\n</tr>\n<tr>\n<td>primary</td>\n<td>是否为主要字段</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>hover</td>\n<td>是否显示hover效果</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>ellipsis</td>\n<td>是否省略</td>\n<td>boolean/object</td>\n<td>false</td>\n</tr>\n<tr>\n<td>sort</td>\n<td>是否支持排序</td>\n<td>boolean/object</td>\n<td>false</td>\n</tr>\n<tr>\n<td>valueOf</td>\n<td>值转换函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>render</td>\n<td>自定义渲染函数</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>groupHeader</td>\n<td>分组表头配置</td>\n<td>array</td>\n<td>-</td>\n</tr>\n<tr>\n<td>disableColItem</td>\n<td>是否禁用ColItem包装</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<h3>列类型(Type)</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>date</td>\n<td>日期(YYYY-MM-DD)</td>\n<td>width: 160, min: 120, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>dateShort</td>\n<td>短日期(YYYY-MM)</td>\n<td>width: 120, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>dateRange</td>\n<td>日期范围</td>\n<td>width: 240, min: 120, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>datetime</td>\n<td>日期时间</td>\n<td>width: 190, min: 190, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>serialNumber</td>\n<td>编号</td>\n<td>width: 190, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>serialNumberShort</td>\n<td>短编号</td>\n<td>width: 120, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>user</td>\n<td>用户</td>\n<td>width: 200, min: 120, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>userName</td>\n<td>用户名</td>\n<td>width: 100, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>contacts</td>\n<td>联系人</td>\n<td>width: 240, min: 160, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>tag</td>\n<td>标签</td>\n<td>width: 140, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>avatar</td>\n<td>头像</td>\n<td>width: 80, min: 64, max: 200</td>\n<td></td>\n</tr>\n<tr>\n<td>singleRow</td>\n<td>单行文本</td>\n<td>width: 70, min: 70, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>hideInfo</td>\n<td>隐藏信息</td>\n<td>width: 120, min: 80, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>mainInfo</td>\n<td>主要信息</td>\n<td>width: 300, min: 160, max: 500</td>\n<td></td>\n</tr>\n<tr>\n<td>description</td>\n<td>描述</td>\n<td>width: 400, min: 160, max: 600</td>\n<td></td>\n</tr>\n<tr>\n<td>options</td>\n<td>操作列</td>\n<td>width: 180, min: 120, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>sensitiveInfo</td>\n<td>敏感信息</td>\n<td>width: 200, min: 100, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>other</td>\n<td>其他</td>\n<td>width: 200, min: 120, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>otherSmall</td>\n<td>其他(小)</td>\n<td>width: 100, min: 70, max: 400</td>\n<td></td>\n</tr>\n<tr>\n<td>otherLarge</td>\n<td>其他(大)</td>\n<td>width: 300, min: 120, max: 500</td>\n<td></td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: true,\n className: ``,\n style: ``,\n list: [{\n title: `基础表格 - 所有列类型展示`,\n description: `展示 Table 组件的 16+ 种列类型(日期、日期时间、短日期、日期范围、编号、短编号、用户、用户名、联系人、头像、标签、隐藏信息、敏感信息、单行文本、描述、其他等),演示 primary、hover、ellipsis、onClick 等常用列属性。业务场景:候选人面试管理系统。`,\n code: `const { default: Table } = _Table;\nconst { PureGlobal } = _Global;\nconst { preset } = reactFetch;\n\nconst ajax = (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n if (config.url === \"/api/v1/user/user/user_key_get\") {\n resolve({\n data: {\n code: 0,\n data: \\`{\"date\":{\"visible\":false},\"serialNumber\":{\"width\":400}}\\`,\n },\n });\n } else if (config.url === \"/api/v1/user/user/user_key_set\") {\n console.log(config.data);\n resolve({\n data: {\n code: 0,\n data: \"\",\n },\n });\n }\n }, 100);\n });\n};\n\npreset({\n ajax,\n});\n\nconst BaseExample = () => {\n return (\n <PureGlobal preset={{ ajax }}>\n <Table\n name=\"candidate-list\"\n controllerOpen={true}\n dataSource={[\n {\n id: \"CAND001\",\n date: \"2024-01-15\",\n dateShort: \"2024-01\",\n dateRange: [\"2024-01-15\", \"2024-03-20\"],\n datetime: \"2024-01-15 14:30:00\",\n serialNumber: \"CAND-2024-001-A001\",\n serialNumberShort: \"C001\",\n userName: \"张明\",\n enUserName: \"Zhang Ming\",\n title: \"高级前端工程师\",\n department: \"技术研发部\",\n tagEnum: \"Y\",\n phoneNumber: \"+86 13800138001\",\n email: \"zhangming@example.com\",\n count: 5,\n description:\n \"拥有8年前端开发经验,精通React、Vue等主流框架,曾主导多个大型项目的技术架构设计,具备优秀的团队协作能力和问题解决能力。\",\n salary: \"35K-45K\",\n avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=ZhangMing\",\n gender: \"M\",\n age: 28,\n education: \"硕士\",\n },\n {\n id: \"CAND002\",\n date: \"2024-01-18\",\n dateShort: \"2024-01\",\n dateRange: [\"2024-01-18\", \"2024-04-15\"],\n datetime: \"2024-01-18 09:15:00\",\n serialNumber: \"CAND-2024-002-B002\",\n serialNumberShort: \"C002\",\n userName: \"李婷\",\n enUserName: \"Li Ting\",\n title: \"产品经理\",\n department: \"产品设计部\",\n tagEnum: null,\n phoneNumber: \"+86 13900139002\",\n email: \"liting@example.com\",\n count: 3,\n description: \"资深产品经理,专注于B端产品设计和用户体验优化。\",\n salary: \"30K-40K\",\n avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=LiTing\",\n gender: \"F\",\n age: 26,\n education: \"本科\",\n },\n {\n id: \"CAND003\",\n date: \"\",\n dateShort: \"2023-12\",\n dateRange: null,\n datetime: \"2024-01-20 16:45:00\",\n serialNumber: \"CAND-2024-003-C003\",\n serialNumberShort: \"C003\",\n userName: \"王强\",\n enUserName: \"Wang Qiang\",\n title: \"后端架构师\",\n department: \"技术研发部\",\n tagEnum: \"Y\",\n phoneNumber: null,\n email: \"wangqiang@example.com\",\n count: 8,\n description: \"10年后端开发经验,擅长微服务架构和分布式系统设计。\",\n salary: \"45K-60K\",\n avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=WangQiang\",\n gender: \"M\",\n age: 32,\n education: \"博士\",\n },\n ]}\n columns={[\n {\n name: \"avatar\",\n title: \"头像\",\n type: \"avatar\",\n valueOf: (item) => ({\n src: item.avatar,\n gender: item.gender,\n }),\n },\n {\n name: \"serialNumber\",\n title: \"候选人编号\",\n type: \"serialNumber\",\n primary: true,\n onClick: async (item) => {\n console.log(\"查看候选人详情:\", item);\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(true);\n }, 500);\n });\n },\n },\n {\n name: \"serialNumberShort\",\n title: \"短编号\",\n type: \"serialNumberShort\",\n },\n {\n name: \"userName\",\n title: \"姓名\",\n type: \"userName\",\n },\n {\n name: \"user\",\n title: \"完整姓名\",\n type: \"user\",\n valueOf: (item) => \\`\\${item.enUserName} \\${item.userName}\\`,\n },\n {\n name: \"title\",\n title: \"职位\",\n type: \"mainInfo\",\n },\n {\n name: \"department\",\n title: \"部门\",\n type: \"other\",\n },\n {\n name: \"date\",\n title: \"面试日期\",\n type: \"date\",\n hover: true,\n },\n {\n name: \"dateShort\",\n title: \"入职月份\",\n type: \"dateShort\",\n },\n {\n name: \"dateRange\",\n title: \"期望入职时间\",\n type: \"dateRange\",\n },\n {\n name: \"datetime\",\n title: \"面试时间\",\n type: \"datetime\",\n },\n {\n name: \"tagEnum\",\n title: \"状态\",\n type: \"tag\",\n valueOf: (item) =>\n item.tagEnum\n ? {\n type: \"success\",\n isEnum: true,\n moduleName: \"marital\",\n name: item.tagEnum,\n }\n : { type: \"warning\", text: \"待审核\" },\n },\n {\n name: \"contacts\",\n title: \"联系方式\",\n type: \"contacts\",\n valueOf: (item) =>\n item.phoneNumber\n ? \\`\\${item.userName} \\${item.phoneNumber}\\`\n : item.email,\n },\n {\n name: \"hideInfo\",\n title: \"手机号\",\n type: \"hideInfo\",\n valueOf: (item) =>\n item.phoneNumber\n ? {\n loader: () => {\n return item.phoneNumber;\n },\n }\n : null,\n },\n {\n name: \"salary\",\n title: \"期望薪资\",\n type: \"hideInfo\",\n valueOf: (item) =>\n item.salary\n ? {\n loader: () => {\n return item.salary;\n },\n }\n : null,\n },\n {\n name: \"count\",\n title: \"面试轮次\",\n type: \"singleRow\",\n },\n {\n name: \"age\",\n title: \"年龄\",\n type: \"otherSmall\",\n },\n {\n name: \"education\",\n title: \"学历\",\n type: \"otherSmall\",\n },\n {\n name: \"description\",\n title: \"简介\",\n type: \"description\",\n ellipsis: true,\n },\n {\n name: \"other\",\n title: \"备注\",\n type: \"otherLarge\",\n render: ({ target }) => {\n return {\n children: \\`候选人: \\${target.userName}, \\${target.title}\\`,\n };\n },\n },\n {\n name: \"options\",\n title: \"操作\",\n type: \"options\",\n valueOf: (item) => [\n {\n onClick: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"通过:\", item.userName);\n resolve();\n }, 1000);\n });\n },\n children: \"通过\",\n isDelete: false,\n },\n {\n onClick: () => {\n console.log(\"安排面试:\", item.userName);\n },\n children: \"安排面试\",\n },\n {\n onClick: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"淘汰:\", item.userName);\n resolve();\n }, 500);\n });\n },\n children: \"淘汰\",\n confirm: true,\n message: \\`确定要淘汰候选人 \\${item.userName} 吗?\\`,\n },\n ],\n },\n ]}\n />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n},{\n name: \"reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_110\n}]\n},{\n title: `列配置详解`,\n description: `详细展示列配置的各种属性,包括 width、min、max 控制列宽,hidden 隐藏列,fixed 固定列,primary 主要字段标识,hover 效果,ellipsis 省略号等。业务场景:项目管理列表。`,\n code: `const { default: Table } = _Table;\nconst { PureGlobal } = _Global;\nconst { preset } = reactFetch;\n\nconst ajax = (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n if (config.url === \"/api/v1/user/user/user_key_get\") {\n resolve({\n data: {\n code: 0,\n data: \"{}\",\n },\n });\n } else if (config.url === \"/api/v1/user/user/user_key_set\") {\n resolve({\n data: { code: 0, data: \"\" },\n });\n }\n }, 100);\n });\n};\n\npreset({ ajax });\n\nconst BaseExample = () => {\n return (\n <PureGlobal preset={{ ajax }}>\n <Table\n name=\"project-list\"\n controllerOpen={true}\n dataSource={[\n {\n id: \"PRJ001\",\n projectName: \"智慧城市管理平台\",\n projectCode: \"SMART-CITY-2024\",\n department: \"技术研发部\",\n pm: \"陈伟\",\n status: \"progress\",\n budget: 1500000,\n progress: 65,\n startDate: \"2024-01-01\",\n endDate: \"2024-06-30\",\n priority: \"high\",\n teamSize: 12,\n description:\n \"基于物联网和大数据技术的智慧城市综合管理平台,包含交通、环保、安防等多个子系统,实现城市运行状态的实时监控和智能调度。\",\n tags: [\"物联网\", \"大数据\", \"微服务\"],\n },\n {\n id: \"PRJ002\",\n projectName: \"电商营销活动系统\",\n projectCode: \"E-COMMERCE-MKT\",\n department: \"产品设计部\",\n pm: \"赵敏\",\n status: \"completed\",\n budget: 800000,\n progress: 100,\n startDate: \"2023-09-01\",\n endDate: \"2024-01-31\",\n priority: \"medium\",\n teamSize: 8,\n description: \"支持多种营销活动的配置和执行,包括优惠券、满减、秒杀等功能。\",\n tags: [\"电商\", \"营销\", \"活动\"],\n },\n {\n id: \"PRJ003\",\n projectName: \"移动端OA办公系统\",\n projectCode: \"MOBILE-OA\",\n department: \"技术研发部\",\n pm: \"刘洋\",\n status: \"pending\",\n budget: 500000,\n progress: 0,\n startDate: \"2024-03-01\",\n endDate: \"2024-08-31\",\n priority: \"low\",\n teamSize: 6,\n description: \"企业移动办公应用,支持审批、考勤、公告等日常办公功能。\",\n tags: [\"移动端\", \"OA\", \"审批\"],\n },\n {\n id: \"PRJ004\",\n projectName: \"数据中台建设\",\n projectCode: \"DATA-PLATFORM\",\n department: \"数据平台部\",\n pm: \"孙磊\",\n status: \"progress\",\n budget: 2000000,\n progress: 45,\n startDate: \"2024-02-01\",\n endDate: \"2024-12-31\",\n priority: \"high\",\n teamSize: 15,\n description: \"构建企业级数据中台,实现数据采集、存储、处理和分析的统一平台。\",\n tags: [\"数据中台\", \"数据治理\", \"BI\"],\n },\n ]}\n columns={[\n {\n name: \"projectCode\",\n title: \"项目编号\",\n type: \"serialNumber\",\n primary: true,\n width: 200,\n min: 150,\n max: 300,\n fixed: \"left\",\n },\n {\n name: \"projectName\",\n title: \"项目名称\",\n type: \"mainInfo\",\n width: 280,\n hover: true,\n fixed: \"left\",\n },\n {\n name: \"department\",\n title: \"所属部门\",\n type: \"other\",\n width: 150,\n hidden: false,\n },\n {\n name: \"pm\",\n title: \"项目经理\",\n type: \"userName\",\n width: 120,\n min: 100,\n max: 200,\n },\n {\n name: \"status\",\n title: \"状态\",\n type: \"tag\",\n width: 120,\n valueOf: (item) => {\n const statusMap = {\n progress: { type: \"processing\", text: \"进行中\" },\n completed: { type: \"success\", text: \"已完成\" },\n pending: { type: \"warning\", text: \"待启动\" },\n };\n return statusMap[item.status];\n },\n },\n {\n name: \"priority\",\n title: \"优先级\",\n type: \"tag\",\n width: 100,\n valueOf: (item) => {\n const priorityMap = {\n high: { type: \"error\", text: \"高\" },\n medium: { type: \"warning\", text: \"中\" },\n low: { type: \"default\", text: \"低\" },\n };\n return priorityMap[item.priority];\n },\n },\n {\n name: \"progress\",\n title: \"进度\",\n type: \"singleRow\",\n width: 100,\n render: ({ target }) => {\n return {\n children: \\`\\${target.progress}%\\`,\n style: {\n color:\n target.progress === 100\n ? \"#52c41a\"\n : target.progress >= 50\n ? \"#1890ff\"\n : \"#faad14\",\n },\n };\n },\n },\n {\n name: \"budget\",\n title: \"预算\",\n type: \"hideInfo\",\n width: 150,\n valueOf: (item) => ({\n loader: () => {\n return \\`¥\\${(item.budget / 10000).toFixed(1)}万\\`;\n },\n }),\n },\n {\n name: \"teamSize\",\n title: \"团队规模\",\n type: \"otherSmall\",\n width: 100,\n hover: true,\n },\n {\n name: \"startDate\",\n title: \"开始日期\",\n type: \"date\",\n width: 160,\n },\n {\n name: \"endDate\",\n title: \"结束日期\",\n type: \"date\",\n width: 160,\n },\n {\n name: \"dateRange\",\n title: \"项目周期\",\n type: \"dateRange\",\n width: 280,\n valueOf: (item) => [item.startDate, item.endDate],\n },\n {\n name: \"description\",\n title: \"项目描述\",\n type: \"description\",\n width: 400,\n min: 200,\n max: 600,\n ellipsis: { showTitle: true },\n },\n {\n name: \"options\",\n title: \"操作\",\n type: \"options\",\n width: 180,\n fixed: \"right\",\n valueOf: (item) => [\n {\n onClick: () => {\n console.log(\"查看项目:\", item.projectName);\n },\n children: \"查看\",\n },\n {\n onClick: () => {\n console.log(\"编辑项目:\", item.projectName);\n },\n children: \"编辑\",\n disabled: item.status === \"completed\",\n tooltipProps: {\n title:\n item.status === \"completed\" ? \"已完成项目不可编辑\" : \"\",\n },\n },\n {\n onClick: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"删除项目:\", item.projectName);\n resolve();\n }, 500);\n });\n },\n children: \"删除\",\n confirm: true,\n message: \\`确定要删除项目 \\${item.projectName} 吗?\\`,\n },\n ],\n },\n ]}\n onTablePropsReady={({ columns, dataSource }) => {\n console.log(\"表格配置就绪:\", { columns, dataSource });\n }}\n />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n},{\n name: \"reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_110\n}]\n},{\n title: `Table 高级功能`,\n description: `展示 Table 组件的高级功能:sticky 固定表头、stickyOffset 表头偏移、pagination 分页、summary 总结栏、scroll 滚动配置、controllerOpen 列控制开关、rowKey 自定义行键、className 自定义样式等。业务场景:订单管理系统。`,\n code: `const { default: Table } = _Table;\nconst { PureGlobal } = _Global;\nconst { preset } = reactFetch;\nconst { Button, Space } = antd;\n\nconst ajax = (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n if (config.url === \"/api/v1/user/user/user_key_get\") {\n resolve({\n data: { code: 0, data: \"{}\" },\n });\n } else if (config.url === \"/api/v1/user/user/user_key_set\") {\n resolve({\n data: { code: 0, data: \"\" },\n });\n }\n }, 100);\n });\n};\n\npreset({ ajax });\n\nconst BaseExample = () => {\n return (\n <PureGlobal preset={{ ajax }}>\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <h3>固定表头 + 分页 + 总结栏</h3>\n <Table\n name=\"order-management\"\n sticky={true}\n stickyOffset=\"60px\"\n pagination={{\n pageSize: 10,\n showSizeChanger: true,\n showQuickJumper: true,\n showTotal: (total) => \\`共 \\${total} 条记录\\`,\n }}\n scroll={{ y: 400 }}\n controllerOpen={true}\n rowKey=\"orderId\"\n className=\"custom-table-class\"\n columnRenderProps={{\n currentUserId: \"user_001\",\n }}\n summary={(current) => {\n const { pageData } = current;\n const totalAmount = pageData.reduce(\n (sum, item) => sum + item.amount,\n 0\n );\n return (\n <Table.Summary fixed>\n <Table.Summary.Row>\n <Table.Summary.Cell index={0} colSpan={5}>\n <strong>本页合计</strong>\n </Table.Summary.Cell>\n <Table.Summary.Cell index={5}>\n <strong>¥{totalAmount.toFixed(2)}</strong>\n </Table.Summary.Cell>\n <Table.Summary.Cell index={6} colSpan={2}>\n <strong>\n {pageData.length} 笔订单\n </strong>\n </Table.Summary.Cell>\n </Table.Summary.Row>\n </Table.Summary>\n );\n }}\n dataSource={[\n {\n orderId: \"ORD202401150001\",\n orderNo: \"ORD-2024-0115-001\",\n customer: \"北京科技有限公司\",\n product: \"企业版SaaS订阅服务\",\n quantity: 50,\n amount: 125000.0,\n status: \"paid\",\n createTime: \"2024-01-15 10:30:00\",\n },\n {\n orderId: \"ORD202401150002\",\n orderNo: \"ORD-2024-0115-002\",\n customer: \"上海创新科技\",\n product: \"高级API调用套餐\",\n quantity: 100000,\n amount: 89000.5,\n status: \"paid\",\n createTime: \"2024-01-15 11:20:00\",\n },\n {\n orderId: \"ORD202401150003\",\n orderNo: \"ORD-2024-0115-003\",\n customer: \"深圳智能制造\",\n product: \"物联网设备管理平台\",\n quantity: 1,\n amount: 350000.0,\n status: \"pending\",\n createTime: \"2024-01-15 14:15:00\",\n },\n {\n orderId: \"ORD202401150004\",\n orderNo: \"ORD-2024-0115-004\",\n customer: \"广州贸易集团\",\n product: \"数据分析平台\",\n quantity: 20,\n amount: 68000.0,\n status: \"shipped\",\n createTime: \"2024-01-15 15:40:00\",\n },\n {\n orderId: \"ORD202401160001\",\n orderNo: \"ORD-2024-0116-001\",\n customer: \"杭州电商公司\",\n product: \"营销自动化工具\",\n quantity: 30,\n amount: 45000.0,\n status: \"paid\",\n createTime: \"2024-01-16 09:00:00\",\n },\n ]}\n columns={[\n {\n name: \"orderNo\",\n title: \"订单号\",\n type: \"serialNumber\",\n primary: true,\n width: 200,\n },\n {\n name: \"customer\",\n title: \"客户名称\",\n type: \"mainInfo\",\n width: 200,\n },\n {\n name: \"product\",\n title: \"产品\",\n type: \"other\",\n width: 200,\n },\n {\n name: \"quantity\",\n title: \"数量\",\n type: \"singleRow\",\n width: 100,\n },\n {\n name: \"amount\",\n title: \"金额\",\n type: \"other\",\n width: 150,\n render: ({ target }) => ({\n children: \\`¥\\${target.amount.toFixed(2)}\\`,\n }),\n },\n {\n name: \"status\",\n title: \"状态\",\n type: \"tag\",\n width: 120,\n valueOf: (item) => {\n const statusMap = {\n paid: { type: \"success\", text: \"已支付\" },\n pending: { type: \"warning\", text: \"待支付\" },\n shipped: { type: \"processing\", text: \"已发货\" },\n cancelled: { type: \"error\", text: \"已取消\" },\n };\n return statusMap[item.status];\n },\n },\n {\n name: \"createTime\",\n title: \"创建时间\",\n type: \"datetime\",\n width: 190,\n },\n ]}\n />\n </div>\n\n <div>\n <h3>自定义行键 + 禁用列控制</h3>\n <Table\n name=\"simple-list\"\n controllerOpen={false}\n rowKey={(record) => \\`custom-key-\\${record.id}\\`}\n dataSource={[\n { id: 1, name: \"张三\", role: \"管理员\", email: \"zhangsan@example.com\" },\n { id: 2, name: \"李四\", role: \"编辑\", email: \"lisi@example.com\" },\n { id: 3, name: \"王五\", role: \"访客\", email: \"wangwu@example.com\" },\n ]}\n columns={[\n { name: \"name\", title: \"姓名\", type: \"userName\" },\n { name: \"role\", title: \"角色\", type: \"other\", width: 120 },\n { name: \"email\", title: \"邮箱\", type: \"other\" },\n ]}\n />\n </div>\n\n <div>\n <h3>横向滚动表格</h3>\n <Table\n name=\"inventory-table\"\n scroll={{ x: 1800 }}\n dataSource={[\n {\n id: \"INV001\",\n productCode: \"SKU-2024-A001\",\n productName: \"智能手表Pro版\",\n category: \"智能穿戴\",\n brand: \"华为\",\n spec: \"42mm/午夜黑\",\n color: \"黑色\",\n stockQty: 1250,\n inTransit: 300,\n warningQty: 200,\n costPrice: 899,\n retailPrice: 1299,\n supplier: \"深圳华为供应链\",\n warehouse: \"A区-3层-15号\",\n updateTime: \"2024-01-15 14:30:00\",\n },\n {\n id: \"INV002\",\n productCode: \"SKU-2024-B002\",\n productName: \"无线降噪耳机\",\n category: \"音频设备\",\n brand: \"索尼\",\n spec: \"头戴式/银色\",\n color: \"银色\",\n stockQty: 856,\n inTransit: 150,\n warningQty: 100,\n costPrice: 1599,\n retailPrice: 2299,\n supplier: \"广州索尼授权经销商\",\n warehouse: \"B区-2层-08号\",\n updateTime: \"2024-01-15 12:20:00\",\n },\n {\n id: \"INV003\",\n productCode: \"SKU-2024-C003\",\n productName: \"机械键盘RGB版\",\n category: \"电脑配件\",\n brand: \"罗技\",\n spec: \"87键/青轴\",\n color: \"黑色\",\n stockQty: 2340,\n inTransit: 500,\n warningQty: 300,\n costPrice: 399,\n retailPrice: 599,\n supplier: \"东莞罗技工厂直供\",\n warehouse: \"C区-1层-22号\",\n updateTime: \"2024-01-15 16:45:00\",\n },\n ]}\n columns={[\n {\n name: \"productCode\",\n title: \"产品编号\",\n type: \"serialNumber\",\n primary: true,\n fixed: \"left\",\n width: 150,\n },\n {\n name: \"productName\",\n title: \"产品名称\",\n type: \"mainInfo\",\n fixed: \"left\",\n width: 180,\n },\n {\n name: \"category\",\n title: \"类别\",\n type: \"tag\",\n width: 120,\n valueOf: (item) => {\n const categoryMap = {\n 智能穿戴: { type: \"processing\", text: \"智能穿戴\" },\n 音频设备: { type: \"success\", text: \"音频设备\" },\n 电脑配件: { type: \"warning\", text: \"电脑配件\" },\n };\n return categoryMap[item.category];\n },\n },\n {\n name: \"brand\",\n title: \"品牌\",\n type: \"other\",\n width: 120,\n },\n {\n name: \"spec\",\n title: \"规格\",\n type: \"other\",\n width: 150,\n },\n {\n name: \"color\",\n title: \"颜色\",\n type: \"otherSmall\",\n width: 100,\n },\n {\n name: \"stockQty\",\n title: \"库存数量\",\n type: \"singleRow\",\n width: 120,\n render: ({ target }) => ({\n children: target.stockQty,\n style: {\n color: target.stockQty < target.warningQty ? \"#f5222d\" : \"#52c41a\",\n fontWeight: \"bold\",\n },\n }),\n },\n {\n name: \"inTransit\",\n title: \"在途数量\",\n type: \"singleRow\",\n width: 120,\n },\n {\n name: \"warningQty\",\n title: \"预警值\",\n type: \"singleRow\",\n width: 100,\n },\n {\n name: \"costPrice\",\n title: \"成本价\",\n type: \"other\",\n width: 120,\n render: ({ target }) => ({\n children: \\`¥\\${target.costPrice}\\`,\n }),\n },\n {\n name: \"retailPrice\",\n title: \"零售价\",\n type: \"other\",\n width: 120,\n render: ({ target }) => ({\n children: \\`¥\\${target.retailPrice}\\`,\n }),\n },\n {\n name: \"supplier\",\n title: \"供应商\",\n type: \"other\",\n width: 180,\n },\n {\n name: \"warehouse\",\n title: \"仓库位置\",\n type: \"other\",\n width: 150,\n },\n {\n name: \"updateTime\",\n title: \"更新时间\",\n type: \"datetime\",\n width: 180,\n },\n {\n name: \"options\",\n title: \"操作\",\n type: \"options\",\n fixed: \"right\",\n width: 150,\n valueOf: (item) => [\n {\n onClick: () => {\n console.log(\"查看详情:\", item.productName);\n },\n children: \"查看\",\n },\n {\n onClick: () => {\n console.log(\"调整库存:\", item.productName);\n },\n children: \"调库\",\n },\n ],\n },\n ]}\n />\n </div>\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n},{\n name: \"reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_110\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_111\n}]\n},{\n title: `TablePage 分页表格`,\n description: `展示 TablePage 组件的完整功能:loader 数据加载(支持分页参数)、featureId 权限控制(自动隐藏指定列)、pagination 详细配置、dataFormat 数据格式化、columns 列配置、columnRenderProps 列渲染属性、summary 总结栏。业务场景:员工管理系统。`,\n code: `const {PureGlobal} = _Global;\nconst {default: Table, TablePage} = _Table;\nconst {range} = lodash;\n\nconst BaseExample = () => {\n return (<PureGlobal\n preset={{\n features: {\n debug: true, profile: {\n id: \"employee-management\", type: \"system\", name: \"员工管理系统\", children: [{\n id: \"employee-list\", type: \"feature\", name: \"员工列表\", options: {\n hiddenColumns: [\"workYears\", \"education\"],\n },\n },],\n },\n },\n }}\n >\n <TablePage\n featureId=\"employee-list\"\n name=\"employee-table\"\n pagination={{\n open: true,\n showSizeChanger: true,\n showQuickJumper: true,\n pageSizeOptions: [\"10\", \"20\", \"50\", \"100\"],\n showTotal: (total) => \\`共 \\${total} 名员工\\`,\n }}\n dataFormat={(data) => {\n return {\n list: data.pageData, total: data.totalCount, data,\n };\n }}\n loader={({data}) => {\n const {currentPage = 1, perPage = 20} = data || {};\n const startIndex = (currentPage - 1) * perPage;\n\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n pageData: range(startIndex, Math.min(startIndex + perPage, 156)).map((index) => ({\n id: \\`EMP\\${String(index + 1).padStart(4, \"0\")}\\`,\n employeeNo: \\`EMP-2024-\\${String(index + 1).padStart(4, \"0\")}\\`,\n name: index % 3 === 0 ? \\`张\\${[\"伟\", \"强\", \"敏\", \"磊\", \"杰\"][index % 5]}\\` : index % 3 === 1 ? \\`李\\${[\"婷\", \"娜\", \"静\", \"丽\", \"娟\"][index % 5]}\\` : \\`王\\${[\"刚\", \"磊\", \"勇\", \"涛\", \"鹏\"][index % 5]}\\`,\n enName: index % 3 === 0 ? \\`Zhang \\${[\"Wei\", \"Qiang\", \"Min\", \"Lei\", \"Jie\"][index % 5]}\\` : index % 3 === 1 ? \\`Li \\${[\"Ting\", \"Na\", \"Jing\", \"Li\", \"Juan\"][index % 5]}\\` : \\`Wang \\${[\"Gang\", \"Lei\", \"Yong\", \"Tao\", \"Peng\"][index % 5]}\\`,\n department: [\"技术研发部\", \"产品设计部\", \"市场营销部\", \"人力资源部\", \"财务部\"][index % 5],\n position: [\"工程师\", \"高级工程师\", \"经理\", \"总监\", \"专员\"][index % 5],\n status: index % 4 === 0 ? \"active\" : index % 4 === 1 ? \"vacation\" : index % 4 === 2 ? \"resigned\" : \"probation\",\n email: \\`employee\\${index + 1}@company.com\\`,\n phone: \\`+86 138\\${String(index).padStart(8, \"0\")}\\`,\n joinDate: \\`2023-\\${String((index % 12) + 1).padStart(2, \"0\")}-\\${String((index % 28) + 1).padStart(2, \"0\")}\\`,\n workYears: Math.floor(index / 12) + 1,\n salary: \\`\\${15 + (index % 20)}K-\\${20 + (index % 20)}K\\`,\n education: [\"本科\", \"硕士\", \"博士\", \"大专\"][index % 4],\n performance: [\"A\", \"B\", \"C\", \"S\"][index % 4],\n })), totalCount: 156,\n });\n }, 300);\n });\n }}\n columns={[{\n name: \"employeeNo\", title: \"工号\", type: \"serialNumber\", primary: true, fixed: \"left\", width: 180,\n }, {\n name: \"name\", title: \"姓名\", type: \"userName\", fixed: \"left\", width: 120,\n }, {\n name: \"enName\", title: \"英文名\", type: \"otherSmall\", width: 120,\n }, {\n name: \"department\", title: \"部门\", type: \"other\", width: 150,\n }, {\n name: \"position\", title: \"职位\", type: \"mainInfo\", width: 180,\n }, {\n name: \"status\", title: \"状态\", type: \"tag\", width: 120, valueOf: (item) => {\n const statusMap = {\n active: {type: \"success\", text: \"在职\"},\n vacation: {type: \"warning\", text: \"休假\"},\n resigned: {type: \"error\", text: \"离职\"},\n probation: {type: \"processing\", text: \"试用期\"},\n };\n return statusMap[item.status];\n },\n }, {\n name: \"performance\", title: \"绩效\", type: \"tag\", width: 100, valueOf: (item) => {\n const perfMap = {\n S: {type: \"success\", text: \"S\"},\n A: {type: \"processing\", text: \"A\"},\n B: {type: \"warning\", text: \"B\"},\n C: {type: \"error\", text: \"C\"},\n };\n return perfMap[item.performance];\n },\n }, {\n name: \"phone\", title: \"手机号\", type: \"hideInfo\", width: 150, valueOf: (item) => ({\n loader: () => item.phone,\n }),\n }, {\n name: \"email\",\n title: \"邮箱\",\n type: \"contacts\",\n width: 200,\n valueOf: (item) => \\`\\${item.name} \\${item.email}\\`,\n }, {\n name: \"joinDate\", title: \"入职日期\", type: \"date\", width: 160,\n }, {\n name: \"workYears\", title: \"工龄\", type: \"singleRow\", width: 100, render: ({target}) => ({\n children: \\`\\${target.workYears}年\\`,\n }),\n }, {\n name: \"salary\", title: \"薪资范围\", type: \"hideInfo\", width: 150, valueOf: (item) => ({\n loader: () => item.salary,\n }),\n }, {\n name: \"education\", title: \"学历\", type: \"otherSmall\", width: 100,\n }, {\n name: \"options\", title: \"操作\", type: \"options\", fixed: \"right\", width: 200, valueOf: (item) => [{\n onClick: () => {\n console.log(\"查看员工:\", item.name);\n }, children: \"查看\",\n }, {\n onClick: () => {\n console.log(\"编辑员工:\", item.name);\n }, children: \"编辑\", disabled: item.status === \"resigned\", tooltipProps: {\n title: item.status === \"resigned\" ? \"离职员工不可编辑\" : \"\",\n },\n }, {\n onClick: () => {\n return new Promise((resolve) => {\n setTimeout(() => {\n console.log(\"导出数据:\", item.name);\n resolve();\n }, 500);\n });\n }, children: \"导出\",\n },],\n },]}\n columnRenderProps={{\n currentUserId: \"admin_001\",\n }}\n summary={(current) => {\n const {pageData, data} = current;\n return (<Table.Summary fixed>\n <Table.Summary.Row>\n <Table.Summary.Cell index={0} colSpan={5}>\n <strong>当前页统计</strong>\n </Table.Summary.Cell>\n <Table.Summary.Cell index={5}>\n <strong>{pageData.length} 人</strong>\n </Table.Summary.Cell>\n <Table.Summary.Cell index={6} colSpan={8}>\n <strong>总员工数: {data?.totalCount || 0} 人</strong>\n </Table.Summary.Cell>\n </Table.Summary.Row>\n </Table.Summary>);\n }}\n />\n </PureGlobal>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"lodash\",\n packageName: \"lodash\",\n component: component_112\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n}]\n},{\n title: `行选择与批量操作`,\n description: `展示 useSelectedRow Hook 的使用方法,实现行选择(checkbox)功能,包括 selectedRowKeys、setSelectedRowKeys、onSelectAll、onSelect 等 API。演示批量审批、批量拒绝、批量导出等常见批量操作场景。业务场景:请假审批系统。`,\n code: `const { default: Table } = _Table;\nconst { PureGlobal } = _Global;\nconst { Button, Space, Typography, message } = antd;\nconst { Text } = Typography;\n\nconst ajax = (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n data: { code: 0, data: \"{}\" },\n });\n }, 100);\n });\n};\n\nconst BaseExample = () => {\n const selectedProps = Table.useSelectedRow({\n rowKey: \"id\",\n });\n \n const { selectedRowKeys, setSelectedRowKeys } = selectedProps;\n\n const handleBatchApprove = () => {\n if (selectedRowKeys.length === 0) {\n message.warning(\"请先选择要审批的记录\");\n return;\n }\n message.success(\\`已批量审批 \\${selectedRowKeys.length} 条记录\\`);\n setSelectedRowKeys([]);\n };\n\n const handleBatchReject = () => {\n if (selectedRowKeys.length === 0) {\n message.warning(\"请先选择要拒绝的记录\");\n return;\n }\n message.info(\\`已批量拒绝 \\${selectedRowKeys.length} 条记录\\`);\n setSelectedRowKeys([]);\n };\n\n const handleBatchExport = () => {\n if (selectedRowKeys.length === 0) {\n message.warning(\"请先选择要导出的记录\");\n return;\n }\n message.info(\\`正在导出 \\${selectedRowKeys.length} 条记录\\`);\n };\n\n return (\n <PureGlobal preset={{ ajax }}>\n <Space direction=\"vertical\" size=\"middle\" style={{ width: \"100%\" }}>\n <div style={{ padding: \"12px\", background: \"#f5f5f5\", borderRadius: \"4px\" }}>\n <Space>\n <Text strong>已选择: {selectedRowKeys.length} 项</Text>\n <Button\n type=\"primary\"\n size=\"small\"\n onClick={handleBatchApprove}\n disabled={selectedRowKeys.length === 0}\n >\n 批量通过\n </Button>\n <Button\n size=\"small\"\n onClick={handleBatchReject}\n disabled={selectedRowKeys.length === 0}\n >\n 批量拒绝\n </Button>\n <Button\n size=\"small\"\n onClick={handleBatchExport}\n disabled={selectedRowKeys.length === 0}\n >\n 批量导出\n </Button>\n <Button\n size=\"small\"\n onClick={() => setSelectedRowKeys([])}\n disabled={selectedRowKeys.length === 0}\n >\n 清空选择\n </Button>\n </Space>\n </div>\n\n <Table\n name=\"leave-approval\"\n controllerOpen={false}\n rowSelection={selectedProps}\n dataSource={[\n {\n id: \"LEAVE001\",\n employeeNo: \"EMP-0001\",\n employeeName: \"张明\",\n department: \"技术研发部\",\n leaveType: \"年假\",\n startDate: \"2024-02-01\",\n endDate: \"2024-02-05\",\n days: 5,\n reason: \"春节回家探亲,需要提前返乡准备\",\n status: \"pending\",\n applyTime: \"2024-01-20 10:30:00\",\n },\n {\n id: \"LEAVE002\",\n employeeNo: \"EMP-0002\",\n employeeName: \"李婷\",\n department: \"产品设计部\",\n leaveType: \"事假\",\n startDate: \"2024-02-10\",\n endDate: \"2024-02-10\",\n days: 1,\n reason: \"个人事务处理\",\n status: \"pending\",\n applyTime: \"2024-01-22 14:15:00\",\n },\n {\n id: \"LEAVE003\",\n employeeNo: \"EMP-0003\",\n employeeName: \"王强\",\n department: \"技术研发部\",\n leaveType: \"病假\",\n startDate: \"2024-01-25\",\n endDate: \"2024-01-26\",\n days: 2,\n reason: \"身体不适,需要休息治疗\",\n status: \"approved\",\n applyTime: \"2024-01-24 09:00:00\",\n },\n {\n id: \"LEAVE004\",\n employeeNo: \"EMP-0004\",\n employeeName: \"赵敏\",\n department: \"市场营销部\",\n leaveType: \"婚假\",\n startDate: \"2024-03-01\",\n endDate: \"2024-03-10\",\n days: 10,\n reason: \"结婚典礼及蜜月旅行\",\n status: \"pending\",\n applyTime: \"2024-01-25 16:20:00\",\n },\n {\n id: \"LEAVE005\",\n employeeNo: \"EMP-0005\",\n employeeName: \"陈伟\",\n department: \"人力资源部\",\n leaveType: \"年假\",\n startDate: \"2024-02-15\",\n endDate: \"2024-02-16\",\n days: 2,\n reason: \"家庭事务处理\",\n status: \"rejected\",\n applyTime: \"2024-01-23 11:00:00\",\n },\n ]}\n columns={[\n {\n name: \"employeeNo\",\n title: \"工号\",\n type: \"serialNumber\",\n width: 150,\n },\n {\n name: \"employeeName\",\n title: \"姓名\",\n type: \"userName\",\n width: 120,\n },\n {\n name: \"department\",\n title: \"部门\",\n type: \"other\",\n width: 150,\n },\n {\n name: \"leaveType\",\n title: \"假期类型\",\n type: \"tag\",\n width: 120,\n valueOf: (item) => {\n const typeMap = {\n 年假: { type: \"success\", text: \"年假\" },\n 事假: { type: \"warning\", text: \"事假\" },\n 病假: { type: \"error\", text: \"病假\" },\n 婚假: { type: \"processing\", text: \"婚假\" },\n };\n return typeMap[item.leaveType];\n },\n },\n {\n name: \"dateRange\",\n title: \"请假时间\",\n type: \"dateRange\",\n width: 280,\n valueOf: (item) => [item.startDate, item.endDate],\n },\n {\n name: \"days\",\n title: \"天数\",\n type: \"singleRow\",\n width: 80,\n },\n {\n name: \"reason\",\n title: \"请假原因\",\n type: \"description\",\n width: 300,\n ellipsis: true,\n },\n {\n name: \"status\",\n title: \"状态\",\n type: \"tag\",\n width: 100,\n valueOf: (item) => {\n const statusMap = {\n pending: { type: \"warning\", text: \"待审批\" },\n approved: { type: \"success\", text: \"已通过\" },\n rejected: { type: \"error\", text: \"已拒绝\" },\n };\n return statusMap[item.status];\n },\n },\n {\n name: \"applyTime\",\n title: \"申请时间\",\n type: \"datetime\",\n width: 180,\n },\n {\n name: \"options\",\n title: \"操作\",\n type: \"options\",\n width: 150,\n valueOf: (item) =>\n item.status === \"pending\"\n ? [\n {\n onClick: () => {\n message.success(\\`已通过 \\${item.employeeName} 的请假申请\\`);\n },\n children: \"通过\",\n },\n {\n onClick: () => {\n message.info(\\`已拒绝 \\${item.employeeName} 的请假申请\\`);\n },\n children: \"拒绝\",\n },\n ]\n : [\n {\n onClick: () => {\n console.log(\"查看详情:\", item);\n },\n children: \"查看\",\n },\n ],\n },\n ]}\n />\n </Space>\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_111\n}]\n},{\n title: `分组表头与排序`,\n description: `展示分组表头(groupHeader)功能,实现多级表头结构。演示 sort 排序功能(单列排序、多列排序)和 onSortChange 排序变更回调。同时展示 disableColItem 禁用 ColItem 包装,实现自定义编辑组件。业务场景:销售数据报表。`,\n code: `const { default: Table } = _Table;\nconst { PureGlobal } = _Global;\nconst { preset } = reactFetch;\nconst { Input } = antd;\n\nconst ajax = (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve({\n data: { code: 0, data: \"{}\" },\n });\n }, 100);\n });\n};\n\npreset({ ajax });\n\nconst ValueEdit = ({ value, targetRender }) => {\n const [isEdit, setIsEdit] = React.useState(false);\n return (\n <span\n onClick={() => {\n setIsEdit(true);\n }}\n >\n {isEdit ? (\n <Input\n type=\"text\"\n size=\"small\"\n defaultValue={value}\n onBlur={() => {\n setIsEdit(false);\n }}\n style={{ width: 150 }}\n />\n ) : (\n targetRender(value)\n )}\n </span>\n );\n};\n\nconst BaseExample = () => {\n return (\n <PureGlobal preset={{ ajax }}>\n <Table\n name=\"sales-report\"\n controllerOpen={true}\n dataSource={[\n {\n id: \"SALE001\",\n region: \"华北区\",\n province: \"北京\",\n city: \"北京\",\n productName: \"企业版SaaS\",\n productCode: \"SAAS-ENT\",\n salesAmount: 1250000.0,\n salesVolume: 50,\n growthRate: 23.5,\n marketShare: 18.2,\n customerCount: 128,\n newCustomerCount: 32,\n repurchaseRate: 85.5,\n avgOrderValue: 9765.6,\n targetCompletion: 92.5,\n },\n {\n id: \"SALE002\",\n region: \"华北区\",\n province: \"天津\",\n city: \"天津\",\n productName: \"专业版SaaS\",\n productCode: \"SAAS-PRO\",\n salesAmount: 890000.0,\n salesVolume: 120,\n growthRate: 15.8,\n marketShare: 12.5,\n customerCount: 95,\n newCustomerCount: 18,\n repurchaseRate: 78.2,\n avgOrderValue: 7416.7,\n targetCompletion: 88.3,\n },\n {\n id: \"SALE003\",\n region: \"华东区\",\n province: \"上海\",\n city: \"上海\",\n productName: \"企业版SaaS\",\n productCode: \"SAAS-ENT\",\n salesAmount: 1680000.0,\n salesVolume: 68,\n growthRate: 35.2,\n marketShare: 22.8,\n customerCount: 156,\n newCustomerCount: 45,\n repurchaseRate: 88.6,\n avgOrderValue: 24705.9,\n targetCompletion: 105.2,\n },\n {\n id: \"SALE004\",\n region: \"华东区\",\n province: \"浙江\",\n city: \"杭州\",\n productName: \"专业版SaaS\",\n productCode: \"SAAS-PRO\",\n salesAmount: 980000.0,\n salesVolume: 95,\n growthRate: 28.6,\n marketShare: 16.3,\n customerCount: 112,\n newCustomerCount: 28,\n repurchaseRate: 82.4,\n avgOrderValue: 10315.8,\n targetCompletion: 95.8,\n },\n {\n id: \"SALE005\",\n region: \"华南区\",\n province: \"广东\",\n city: \"深圳\",\n productName: \"企业版SaaS\",\n productCode: \"SAAS-ENT\",\n salesAmount: 1420000.0,\n salesVolume: 58,\n growthRate: 19.3,\n marketShare: 19.6,\n customerCount: 138,\n newCustomerCount: 35,\n repurchaseRate: 86.2,\n avgOrderValue: 24482.8,\n targetCompletion: 89.5,\n },\n ]}\n columns={[\n {\n name: \"region\",\n title: \"大区\",\n type: \"other\",\n width: 100,\n groupHeader: [\n { name: \"area\", title: \"区域信息\" },\n ],\n },\n {\n name: \"province\",\n title: \"省份\",\n type: \"other\",\n width: 100,\n groupHeader: [\n { name: \"area\", title: \"区域信息\" },\n ],\n },\n {\n name: \"city\",\n title: \"城市\",\n type: \"other\",\n width: 100,\n groupHeader: [\n { name: \"area\", title: \"区域信息\" },\n ],\n },\n {\n name: \"productName\",\n title: \"产品名称\",\n type: \"mainInfo\",\n width: 150,\n groupHeader: [\n { name: \"product\", title: \"产品信息\" },\n ],\n },\n {\n name: \"productCode\",\n title: \"产品编码\",\n type: \"serialNumber\",\n width: 150,\n groupHeader: [\n { name: \"product\", title: \"产品信息\" },\n ],\n },\n {\n name: \"salesAmount\",\n title: \"销售金额\",\n type: \"other\",\n width: 150,\n sort: { single: true },\n render: ({ target }) => ({\n children: \\`¥\\${(target.salesAmount / 10000).toFixed(2)}万\\`,\n }),\n groupHeader: [\n { name: \"sales\", title: \"销售业绩\" },\n ],\n },\n {\n name: \"salesVolume\",\n title: \"销售数量\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n groupHeader: [\n { name: \"sales\", title: \"销售业绩\" },\n ],\n },\n {\n name: \"growthRate\",\n title: \"增长率\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n render: ({ target }) => ({\n children: \\`\\${target.growthRate}%\\`,\n style: {\n color: target.growthRate > 20 ? \"#52c41a\" : target.growthRate > 10 ? \"#1890ff\" : \"#faad14\",\n },\n }),\n groupHeader: [\n { name: \"sales\", title: \"销售业绩\" },\n ],\n },\n {\n name: \"marketShare\",\n title: \"市场份额\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n render: ({ target }) => ({\n children: \\`\\${target.marketShare}%\\`,\n }),\n groupHeader: [\n { name: \"market\", title: \"市场分析\" },\n ],\n },\n {\n name: \"customerCount\",\n title: \"客户总数\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n groupHeader: [\n { name: \"market\", title: \"市场分析\" },\n ],\n },\n {\n name: \"newCustomerCount\",\n title: \"新增客户\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n groupHeader: [\n { name: \"market\", title: \"市场分析\" },\n ],\n },\n {\n name: \"repurchaseRate\",\n title: \"复购率\",\n type: \"singleRow\",\n width: 120,\n sort: true,\n render: ({ target }) => ({\n children: \\`\\${target.repurchaseRate}%\\`,\n }),\n groupHeader: [\n { name: \"customer\", title: \"客户指标\" },\n ],\n },\n {\n name: \"avgOrderValue\",\n title: \"客单价\",\n type: \"other\",\n width: 130,\n sort: true,\n render: ({ target }) => ({\n children: \\`¥\\${target.avgOrderValue.toFixed(2)}\\`,\n }),\n groupHeader: [\n { name: \"customer\", title: \"客户指标\" },\n ],\n },\n {\n name: \"targetCompletion\",\n title: \"目标完成率\",\n type: \"singleRow\",\n width: 140,\n sort: true,\n render: ({ target }) => ({\n children: \\`\\${target.targetCompletion}%\\`,\n style: {\n color: target.targetCompletion >= 100 ? \"#52c41a\" : target.targetCompletion >= 90 ? \"#1890ff\" : \"#faad14\",\n },\n }),\n groupHeader: [\n { name: \"target\", title: \"目标达成\" },\n ],\n },\n {\n name: \"editableField\",\n title: \"备注\",\n type: \"other\",\n width: 150,\n disableColItem: true,\n valueOf: (item, { targetRender }) => (\n <ValueEdit value=\"点击编辑备注\" targetRender={targetRender} />\n ),\n groupHeader: [\n { name: \"target\", title: \"目标达成\" },\n ],\n },\n {\n name: \"options\",\n title: \"操作\",\n type: \"options\",\n fixed: \"right\",\n width: 150,\n valueOf: (item) => [\n {\n onClick: () => {\n console.log(\"查看详情:\", item.city);\n },\n children: \"查看详情\",\n },\n {\n onClick: () => {\n console.log(\"生成报告:\", item.city);\n },\n children: \"生成报告\",\n },\n ],\n },\n ]}\n onSortChange={(sort) => {\n console.log(\"排序变更:\", sort);\n }}\n onTablePropsReady={({ columns, dataSource }) => {\n console.log(\"表格就绪:\", { columns, dataSource });\n }}\n />\n </PureGlobal>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Table\",\n packageName: \"@components/Table\",\n component: component_108\n},{\n name: \"_Global\",\n packageName: \"@components/Global\",\n component: component_109\n},{\n name: \"reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_110\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_111\n}]\n}]\n }\n};\nexport default readmeConfig;\n","import * as component_113 from '@components/Tooltip';\nimport * as component_114 from 'antd';\nimport * as component_115 from '@kne/remote-loader';\nimport * as component_116 from '@kne/react-fetch';\nimport * as component_117 from '@components/Descriptions';\nconst readmeConfig = {\n name: `Tooltip`,\n summary: `<p>Tooltip 组件是一个功能强大的文字提示气泡框,基于 Ant Design Tooltip 二次封装,提供了丰富的内容展示能力。</p>\n<p>组件支持三种使用方式:</p>\n<ul>\n<li><strong>Tooltip</strong>: 基础提示组件,支持标题、内容、重要信息、副标题等多种内容组合</li>\n<li><strong>TooltipFetch</strong>: 集成远程数据加载的提示组件,适用于需要动态获取数据的场景</li>\n<li><strong>TooltipInfoLabel</strong>: 带信息图标的标签组件,常用于表单字段标签</li>\n</ul>\n<p>主要特性:</p>\n<ul>\n<li>支持多种内容组合(标题、内容、重要信息、副标题)</li>\n<li>支持 3 种尺寸(small、默认、large)</li>\n<li>支持重要信息类型(success、warning、error)</li>\n<li>支持嵌入自定义内容(如表单、图表等)</li>\n<li>支持远程数据加载和缓存</li>\n<li>支持多种触发方式(hover、click、focus 等)</li>\n</ul>`,\n \n \n api: `<h3>Tooltip 组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>size</td>\n<td>提示框宽度,可选值:small(240px)、默认(360px)、large(480px)</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>title</td>\n<td>标题内容</td>\n<td>string/ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>content</td>\n<td>主要内容</td>\n<td>string/ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>subtitle</td>\n<td>副标题内容</td>\n<td>string/ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>importantInfo</td>\n<td>重要提示信息</td>\n<td>string/ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>importantInfoType</td>\n<td>重要信息类型,可选值:success、warning、error</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>showInfo</td>\n<td>是否显示标题旁的提示图标</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n<tr>\n<td>moreInfo</td>\n<td>扩展内容区域,可嵌入表单、图表等</td>\n<td>ReactNode</td>\n<td>-</td>\n</tr>\n<tr>\n<td>trigger</td>\n<td>触发方式,可选值:hover、click、focus</td>\n<td>string</td>\n<td>'hover'</td>\n</tr>\n<tr>\n<td>placement</td>\n<td>气泡框位置</td>\n<td>string</td>\n<td>'top'</td>\n</tr>\n<tr>\n<td>overlayClassName</td>\n<td>自定义气泡框类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>\n<h3>TooltipFetch 组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>api</td>\n<td>数据接口配置,参考 @kne/react-fetch</td>\n<td>object</td>\n<td>-</td>\n</tr>\n<tr>\n<td>fetchContent</td>\n<td>数据转换函数,接收接口返回数据,返回 Tooltip 的 props</td>\n<td>function</td>\n<td>-</td>\n</tr>\n<tr>\n<td>showLoading</td>\n<td>是否显示加载状态</td>\n<td>boolean</td>\n<td>true</td>\n</tr>\n<tr>\n<td>loadingClassName</td>\n<td>加载动画的自定义类名</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>force</td>\n<td>是否每次显示都重新加载数据</td>\n<td>boolean</td>\n<td>false</td>\n</tr>\n</tbody>\n</table>\n<h3>TooltipInfoLabel 组件</h3>\n<table>\n<thead>\n<tr>\n<th>属性名</th>\n<th>说明</th>\n<th>类型</th>\n<th>默认值</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>标签文字</td>\n<td>string</td>\n<td>-</td>\n</tr>\n<tr>\n<td>tooltipTitle</td>\n<td>Tooltip 的属性对象,会传递给 Tooltip 组件</td>\n<td>object</td>\n<td>-</td>\n</tr>\n</tbody>\n</table>`,\n example: {\n isFull: false,\n className: ``,\n style: ``,\n list: [{\n title: `基础用法`,\n description: `展示 Tooltip 组件的基础用法,包括纯文本提示、带标题的提示、带副标题的提示、点击触发方式以及自定义位置等常用场景。`,\n code: `const { default: Tooltip } = _Tooltip;\nconst { Space, Button, Tag, Typography } = antd;\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <Text strong>基础用法 - 纯文本提示</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip content=\"这是一段简单的提示文本,用于解释说明。\">\n <Tag color=\"blue\">简单提示</Tag>\n </Tooltip>\n <Tooltip content=\"审批流程需要经过部门主管、财务部门、总经理三级审批,整个流程预计需要3-5个工作日完成。\">\n <Tag color=\"green\">流程说明</Tag>\n </Tooltip>\n </Space>\n </div>\n\n <div>\n <Text strong>带标题的提示</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip\n title=\"数据统计规则\"\n content=\"统计范围:2024年1月1日至当前日期的所有有效订单数据。\"\n >\n <Tag color=\"purple\">销售额统计</Tag>\n </Tooltip>\n <Tooltip\n title=\"权限说明\"\n content=\"仅系统管理员和部门主管可以查看完整的员工薪资信息,普通用户只能看到薪资范围。\"\n >\n <Tag color=\"orange\">薪资权限</Tag>\n </Tooltip>\n </Space>\n </div>\n\n <div>\n <Text strong>带副标题的提示</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip\n title=\"候选人推荐指数\"\n subtitle=\"计算规则:\"\n content=\"根据候选人的面试评分、项目经验、技能匹配度、薪资期望等多个维度综合计算得出。\"\n >\n <Tag color=\"cyan\">推荐算法</Tag>\n </Tooltip>\n </Space>\n </div>\n\n <div>\n <Text strong>点击触发</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip\n trigger=\"click\"\n title=\"操作指南\"\n content='点击\"编辑\"按钮可以修改订单信息,点击\"取消\"按钮可以撤销订单,点击\"导出\"按钮可以导出订单详情。'\n >\n <Button size=\"small\">查看操作说明</Button>\n </Tooltip>\n </Space>\n </div>\n\n <div>\n <Text strong>自定义位置</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip placement=\"top\" content=\"顶部提示 Top\">\n <Button size=\"small\">Top</Button>\n </Tooltip>\n <Tooltip placement=\"bottom\" content=\"底部提示 Bottom\">\n <Button size=\"small\">Bottom</Button>\n </Tooltip>\n <Tooltip placement=\"left\" content=\"左侧提示 Left\">\n <Button size=\"small\">Left</Button>\n </Tooltip>\n <Tooltip placement=\"right\" content=\"右侧提示 Right\">\n <Button size=\"small\">Right</Button>\n </Tooltip>\n </Space>\n </div>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n},{\n title: `不同尺寸`,\n description: `展示 Tooltip 组件的三种尺寸(small 240px、默认 360px、large 480px),以及在实际业务场景中如何选择合适的尺寸。`,\n code: `const { default: Tooltip } = _Tooltip;\nconst { Space, Typography } = antd;\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <Text strong>小尺寸提示框 (240px)</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n size=\"small\"\n title=\"快速筛选\"\n content=\"支持按状态、时间、部门等维度进行数据筛选。\"\n >\n <Text code style={{ cursor: \"pointer\" }}>\n 小尺寸提示\n </Text>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>默认尺寸提示框 (360px)</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n title=\"项目进度说明\"\n content=\"项目进度根据已完成任务数占总任务数的比例计算。进度低于30%显示红色,30%-70%显示黄色,高于70%显示绿色。\"\n >\n <Text code style={{ cursor: \"pointer\" }}>\n 默认尺寸提示\n </Text>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>大尺寸提示框 (480px)</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n size=\"large\"\n title=\"绩效评估规则\"\n content=\"绩效评估采用360度评估法,包括自评(20%)、上级评分(40%)、同事评分(20%)、下属评分(20%)四个维度。评估周期为每季度一次,年度绩效为四个季度的平均值。评估等级分为:S(卓越)、A(优秀)、B(良好)、C(合格)、D(待改进)。\"\n >\n <Text code style={{ cursor: \"pointer\" }}>\n 大尺寸提示\n </Text>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>实际应用场景对比</Text>\n <Space style={{ marginTop: 12 }}>\n <Tooltip\n size=\"small\"\n title=\"快捷操作\"\n content=\"双击行可快速编辑\"\n >\n <a href=\"#\">编辑提示</a>\n </Tooltip>\n <Tooltip\n title=\"数据说明\"\n content=\"本月销售额为1,256,800元,环比增长15.3%,同比增长28.7%。主要增长来源为新客户开发和老客户复购。\"\n >\n <a href=\"#\">销售数据</a>\n </Tooltip>\n <Tooltip\n size=\"large\"\n title=\"系统更新日志\"\n content=\"v2.3.0 (2024-01-15): 1. 新增批量导入功能;2. 优化搜索性能,响应速度提升50%;3. 修复已知bug 12个;4. 升级UI设计,提升用户体验。v2.2.0 (2024-01-01): 1. 新增数据导出功能;2. 支持多语言切换。\"\n >\n <a href=\"#\">版本记录</a>\n </Tooltip>\n </Space>\n </div>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n},{\n title: `重要信息提示`,\n description: `展示如何使用 importantInfo 属性突出显示重要信息,支持 success、warning、error 三种类型,适用于审核状态、库存预警、支付结果等业务场景。`,\n code: `const { default: Tooltip } = _Tooltip;\nconst { Space, Typography, Tag } = antd;\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <Text strong>成功类型的重要信息</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n title=\"审核通过\"\n importantInfo=\"恭喜!您的项目申请已通过审核,可以进行下一步操作。\"\n importantInfoType=\"success\"\n content=\"审核意见:项目方案合理,预算充足,团队成员配置得当,同意立项。请于3个工作日内完成项目启动准备工作。\"\n >\n <Tag color=\"success\" style={{ cursor: \"pointer\" }}>\n 审核状态\n </Tag>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>警告类型的重要信息</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n title=\"库存预警\"\n importantInfo=\"当前库存量已低于安全库存线,请及时补货!\"\n importantInfoType=\"warning\"\n content=\"商品【华为Mate 60 Pro】当前库存:156台,安全库存:200台。建议立即联系供应商补充库存,避免出现缺货情况。\"\n >\n <Tag color=\"warning\" style={{ cursor: \"pointer\" }}>\n 库存状态\n </Tag>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>错误类型的重要信息</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n title=\"付款失败\"\n importantInfo=\"订单付款失败,请检查支付信息后重试!\"\n importantInfoType=\"error\"\n subtitle=\"失败原因:\"\n content=\"银行卡余额不足。订单金额:¥15,680.00,银行卡余额:¥12,350.00。请更换支付方式或充值后重试。\"\n >\n <Tag color=\"error\" style={{ cursor: \"pointer\" }}>\n 支付状态\n </Tag>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>复杂信息展示</Text>\n <div style={{ marginTop: 12 }}>\n <Tooltip\n title=\"候选人评估报告\"\n importantInfo=\"综合评分:A级(强烈推荐)\"\n importantInfoType=\"success\"\n subtitle=\"评分详情:\"\n content={\n <div>\n <div>• 技术能力:90分(优秀)</div>\n <div>• 项目经验:85分(良好)</div>\n <div>• 沟通能力:88分(良好)</div>\n <div>• 团队协作:92分(优秀)</div>\n <div>• 学习能力:95分(卓越)</div>\n </div>\n }\n >\n <Tag color=\"blue\" style={{ cursor: \"pointer\" }}>\n 查看评估\n </Tag>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>实际业务场景 - 数据统计说明</Text>\n <div style={{ marginTop: 12 }}>\n <Space>\n <Tooltip\n title=\"客户转化率\"\n importantInfo=\"本月转化率较上月提升5.2%,表现优异!\"\n importantInfoType=\"success\"\n content=\"潜在客户:1,256人 → 初步接触:892人 → 深度沟通:456人 → 成交:287人。转化漏斗各环节转化率分别为:71%、51%、63%。\"\n >\n <a href=\"#\">转化漏斗</a>\n </Tooltip>\n <Tooltip\n title=\"异常数据提醒\"\n importantInfo=\"检测到3条异常数据,请及时处理!\"\n importantInfoType=\"warning\"\n content=\"订单#202401150001:金额异常(超出历史平均值的5倍);订单#202401150002:收货地址异常(无法定位);订单#202401150003:支付时间异常(耗时过长)。\"\n >\n <a href=\"#\">异常监控</a>\n </Tooltip>\n </Space>\n </div>\n </div>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n},{\n title: `嵌入表单内容`,\n description: `展示如何在 Tooltip 中嵌入表单组件(如筛选表单、审批表单),实现快速操作功能,适用于批量操作、数据导出等复杂交互场景。`,\n code: `const {default: Tooltip} = _Tooltip;\nconst {createWithRemoteLoader} = remoteLoader;\nconst {Space, Typography, Button} = antd;\nconst {Text} = Typography;\n\nconst BaseExample = createWithRemoteLoader({\n modules: [\"components-core:FormInfo\", \"components-core:Global@PureGlobal\"],\n})(({remoteModules}) => {\n const [FormInfo, PureGlobal] = remoteModules;\n const {Form, SubmitButton, CancelButton} = FormInfo;\n const {Input, TextArea} = FormInfo.fields;\n\n const FilterForm = () => {\n return (<Form\n onSubmit={(data) => {\n console.log(\"筛选条件:\", data);\n }}\n >\n <Space direction=\"vertical\" size=\"small\">\n <Input\n name=\"productName\"\n label=\"产品名称\"\n placeholder=\"请输入产品名称\"\n />\n <Input\n name=\"productCode\"\n label=\"产品编号\"\n placeholder=\"请输入产品编号\"\n />\n <TextArea\n name=\"description\"\n label=\"备注说明\"\n placeholder=\"请输入备注说明\"\n rows={3}\n />\n <Space style={{width: \"100%\", justifyContent: \"flex-end\"}}>\n <CancelButton>取消</CancelButton>\n <SubmitButton>确定</SubmitButton>\n </Space>\n </Space>\n </Form>);\n };\n\n const ApprovalForm = () => {\n return (<Form\n onSubmit={(data) => {\n console.log(\"审批意见:\", data);\n }}\n >\n <Space direction=\"vertical\" size=\"small\">\n <Input\n name=\"approver\"\n label=\"审批人\"\n placeholder=\"请输入审批人姓名\"\n />\n <TextArea\n name=\"comment\"\n label=\"审批意见\"\n placeholder=\"请输入审批意见\"\n rows={4}\n />\n <Space style={{width: \"100%\", justifyContent: \"flex-end\"}}>\n <CancelButton>拒绝</CancelButton>\n <SubmitButton type=\"primary\">通过</SubmitButton>\n </Space>\n </Space>\n </Form>);\n };\n\n return (<PureGlobal>\n <Space direction=\"vertical\" size=\"large\" style={{width: \"100%\"}}>\n <div>\n <Text strong>快速筛选功能</Text>\n <div style={{marginTop: 12}}>\n <Tooltip\n trigger=\"click\"\n size=\"large\"\n title=\"高级筛选\"\n moreInfo={<FilterForm/>}\n >\n <Button type=\"primary\">打开筛选面板</Button>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>快速审批功能</Text>\n <div style={{marginTop: 12}}>\n <Tooltip\n trigger=\"click\"\n size=\"large\"\n title=\"快速审批\"\n content=\"请填写审批意见后提交:\"\n moreInfo={<ApprovalForm/>}\n >\n <Button type=\"primary\" danger>\n 快速审批\n </Button>\n </Tooltip>\n </div>\n </div>\n\n <div>\n <Text strong>实际应用场景</Text>\n <div style={{marginTop: 12}}>\n <Space>\n <Tooltip\n trigger=\"click\"\n title=\"批量操作\"\n content=\"已选择 12 条记录\"\n moreInfo={<Space direction=\"vertical\" style={{marginTop: 12}}>\n <Button size=\"small\" block>\n 批量删除\n </Button>\n <Button size=\"small\" block>\n 批量导出\n </Button>\n <Button size=\"small\" block>\n 批量修改状态\n </Button>\n </Space>}\n >\n <Button>批量操作</Button>\n </Tooltip>\n\n <Tooltip\n trigger=\"click\"\n size=\"large\"\n title=\"数据导出设置\"\n content=\"请选择导出字段和格式:\"\n moreInfo={<Space direction=\"vertical\" size=\"small\" style={{marginTop: 12}}>\n <Text>导出字段:</Text>\n <Space wrap>\n <Text code>订单号</Text>\n <Text code>客户名称</Text>\n <Text code>金额</Text>\n <Text code>状态</Text>\n <Text code>创建时间</Text>\n </Space>\n <Text>导出格式:</Text>\n <Space>\n <Button size=\"small\">Excel</Button>\n <Button size=\"small\">CSV</Button>\n <Button size=\"small\">PDF</Button>\n </Space>\n </Space>}\n >\n <Button>导出数据</Button>\n </Tooltip>\n </Space>\n </div>\n </div>\n </Space>\n </PureGlobal>);\n});\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"remoteLoader\",\n packageName: \"@kne/remote-loader\",\n component: component_115\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n},{\n title: `TooltipInfoLabel 标签组件`,\n description: `展示 TooltipInfoLabel 组件的使用方法,该组件结合了标签和提示功能,常用于表单字段标签,可以快速为字段添加帮助说明和重要提示。`,\n code: `const { TooltipInfoLabel } = _Tooltip;\nconst { Space, Typography, Divider } = antd;\nconst { Text } = Typography;\n\nconst BaseExample = () => {\n return (\n <Space direction=\"vertical\" size=\"large\" style={{ width: \"100%\" }}>\n <div>\n <Text strong>基础用法 - 带提示的标签</Text>\n <div style={{ marginTop: 12 }}>\n <Space direction=\"vertical\" size=\"small\">\n <TooltipInfoLabel\n title=\"客户名称\"\n tooltipTitle={{\n content: \"请填写客户的全称,用于合同签署和发票开具。\",\n }}\n />\n <TooltipInfoLabel\n title=\"联系人\"\n tooltipTitle={{\n content: \"客户方的主要联系人,建议填写项目负责人。\",\n }}\n />\n <TooltipInfoLabel\n title=\"联系电话\"\n tooltipTitle={{\n content: \"联系人电话,支持手机号和座机号,格式:区号-座机号或手机号。\",\n }}\n />\n </Space>\n </div>\n </div>\n\n <Divider />\n\n <div>\n <Text strong>带重要信息的标签</Text>\n <div style={{ marginTop: 12 }}>\n <Space direction=\"vertical\" size=\"small\">\n <TooltipInfoLabel\n title=\"销售额统计周期\"\n tooltipTitle={{\n importantInfo: \"统计周期为自然月,每月1日0点至月末23:59:59。\",\n importantInfoType: \"success\",\n content: \"例如:2024年1月的统计周期为2024-01-01 00:00:00至2024-01-31 23:59:59。\",\n }}\n />\n <TooltipInfoLabel\n title=\"库存预警阈值\"\n tooltipTitle={{\n importantInfo: \"库存低于此值时系统将自动发送补货提醒。\",\n importantInfoType: \"warning\",\n content: \"建议根据历史销量和补货周期设置合理的预警阈值,一般设置为安全库存的80%。\",\n }}\n />\n <TooltipInfoLabel\n title=\"审批截止时间\"\n tooltipTitle={{\n importantInfo: \"超过截止时间未审批将自动流转至上一级审批人!\",\n importantInfoType: \"error\",\n content: \"普通审批:24小时内;紧急审批:4小时内;特急审批:1小时内。\",\n }}\n />\n </Space>\n </div>\n </div>\n\n <Divider />\n\n <div>\n <Text strong>复杂信息标签</Text>\n <div style={{ marginTop: 12 }}>\n <Space direction=\"vertical\" size=\"small\">\n <TooltipInfoLabel\n title=\"候选人评分规则\"\n tooltipTitle={{\n title: \"评分维度说明\",\n importantInfo: \"综合评分由技术能力、项目经验、沟通能力、团队协作四个维度组成。\",\n subtitle: \"权重分配:\",\n content: \"技术能力(40%)、项目经验(30%)、沟通能力(15%)、团队协作(15%)。评分采用百分制,90分以上为A级,80-89分为B级,60-79分为C级,60分以下为D级。\",\n }}\n />\n <TooltipInfoLabel\n title=\"项目优先级\"\n tooltipTitle={{\n title: \"优先级判定规则\",\n importantInfo: \"P0级项目:公司战略项目,需最高优先级处理\",\n importantInfoType: \"error\",\n subtitle: \"优先级定义:\",\n content: \"P0:战略级(影响公司业务发展);P1:重要级(影响部门KPI);P2:普通级(常规业务需求);P3:优化级(体验优化类)。\",\n }}\n />\n <TooltipInfoLabel\n title=\"数据权限说明\"\n tooltipTitle={{\n title: \"权限范围\",\n content: \"系统管理员:全部数据;部门主管:本部门数据;普通员工:个人数据;只读用户:仅可查看,不可编辑。\",\n }}\n />\n </Space>\n </div>\n </div>\n\n <Divider />\n\n <div>\n <Text strong>实际应用场景 - 表单字段标签</Text>\n <div\n style={{\n marginTop: 12,\n padding: 16,\n background: \"#f5f5f5\",\n borderRadius: 4,\n }}\n >\n <Space direction=\"vertical\" size=\"middle\" style={{ width: \"100%\" }}>\n <div>\n <TooltipInfoLabel\n title=\"订单编号\"\n tooltipTitle={{\n content: \"系统自动生成,格式:ORD-YYYYMMDD-序号\",\n }}\n />\n <Text type=\"secondary\" style={{ marginLeft: 8 }}>\n ORD-20240115-001\n </Text>\n </div>\n <div>\n <TooltipInfoLabel\n title=\"预计交付日期\"\n tooltipTitle={{\n importantInfo: \"请在交付日期前至少3天完成生产准备!\",\n importantInfoType: \"warning\",\n content: \"交付日期考虑了生产周期、质检时间和物流时间,请务必按时完成。\",\n }}\n />\n <Text type=\"secondary\" style={{ marginLeft: 8 }}>\n 2024-02-15\n </Text>\n </div>\n <div>\n <TooltipInfoLabel\n title=\"付款方式\"\n tooltipTitle={{\n title: \"付款方式说明\",\n content: \"支持:全款预付、分期付款、货到付款三种方式。分期付款需签订补充协议。\",\n }}\n />\n <Text type=\"secondary\" style={{ marginLeft: 8 }}>\n 分期付款(30%预付款)\n </Text>\n </div>\n </Space>\n </div>\n </div>\n </Space>\n );\n};\n\nrender(<BaseExample />);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n},{\n title: `远程数据加载`,\n description: `展示 TooltipFetch 组件的使用方法,该组件支持从远程接口加载数据并动态展示,适用于员工信息、订单详情、库存信息等需要实时数据的场景。支持数据缓存和强制刷新。`,\n code: `const {TooltipFetch} = _Tooltip;\nconst {preset} = reactFetch;\nconst {Space, Tag, Typography, Card, Avatar} = antd;\nconst {Text, Title} = Typography;\nconst {default: Descriptions} = _Descriptions;\n\npreset({\n ajax: (config) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n if (config.url === \"/api/employee/detail\") {\n resolve({\n data: {\n code: 0, data: {\n employeeId: \"EMP-2024-001\",\n name: \"张明\",\n avatar: \"https://api.dicebear.com/7.x/avataaars/svg?seed=ZhangMing\",\n department: \"技术研发部\",\n position: \"高级前端工程师\",\n email: \"zhangming@company.com\",\n phone: \"+86 138-0001-2345\",\n joinDate: \"2022-03-15\",\n performance: \"A\",\n skills: [\"React\", \"Vue\", \"TypeScript\", \"Node.js\"],\n },\n },\n });\n } else if (config.url === \"/api/order/detail\") {\n resolve({\n data: {\n code: 0, data: {\n orderId: \"ORD-2024-001\",\n customer: \"腾讯科技有限公司\",\n product: \"企业版SaaS订阅服务\",\n amount: 125000.0,\n status: \"已完成\",\n createDate: \"2024-01-10\",\n salesPerson: \"李婷\",\n paymentMethod: \"分期付款\",\n completionRate: 100,\n },\n },\n });\n } else if (config.url === \"/api/product/inventory\") {\n resolve({\n data: {\n code: 0, data: {\n productId: \"SKU-001\",\n productName: \"华为Mate 60 Pro\",\n stock: 156,\n inTransit: 50,\n reserved: 20,\n available: 86,\n warningLevel: 200,\n lastUpdate: \"2024-01-15 10:30:00\",\n },\n },\n });\n }\n }, 800);\n });\n },\n});\n\nconst BaseExample = () => {\n return (<Space direction=\"vertical\" size=\"large\" style={{width: \"100%\"}}>\n <div>\n <Text strong>员工信息快速查看</Text>\n <div style={{marginTop: 12}}>\n <TooltipFetch\n api={{url: \"/api/employee/detail\"}}\n size=\"large\"\n fetchContent={(data) => {\n return ({\n content: (<div style={{width: '500px'}}><Space direction=\"vertical\" size=\"small\">\n <div style={{display: \"flex\", alignItems: \"center\", gap: 12}}>\n <Avatar src={data.avatar} size={48}/>\n <div>\n <Text strong style={{fontSize: 16}}>\n {data.name}\n </Text>\n <br/>\n <Text type=\"secondary\">\n {data.department} · {data.position}\n </Text>\n </div>\n </div>\n <Descriptions\n size=\"small\"\n dataSource={[[{label: \"工号\", content: data.employeeId}, {\n label: \"邮箱\", content: data.email\n }], [{label: \"电话\", content: data.phone}, {\n label: \"入职日期\", content: data.joinDate\n }], [{label: \"绩效\", content: data.performance}, {\n label: \"技能\", content: data.skills.join(\"、\")\n }]]}\n />\n </Space></div>),\n });\n }}\n >\n <Tag color=\"blue\" style={{cursor: \"pointer\"}}>\n 张明 - 高级前端工程师\n </Tag>\n </TooltipFetch>\n </div>\n </div>\n\n <div>\n <Text strong>订单详情快速查看</Text>\n <div style={{marginTop: 12}}>\n <TooltipFetch\n api={{url: \"/api/order/detail\"}}\n size=\"large\"\n fetchContent={(data) => ({\n title: \"订单详情\", content: (<div style={{width: '500px'}}><Descriptions\n size=\"small\"\n dataSource={[[{label: \"订单号\", content: data.orderId}, {\n label: \"客户\", content: data.customer\n }], [{label: \"产品\", content: data.product}, {\n label: \"金额\", content: \\`¥\\${data.amount.toLocaleString()}\\`\n }], [{\n label: \"状态\", content: <Tag color=\"success\">{data.status}</Tag>\n }, {label: \"完成率\", content: \\`\\${data.completionRate}%\\`}, {\n label: \"创建日期\", content: data.createDate\n }], [{label: \"销售\", content: data.salesPerson}, {\n label: \"付款方式\", content: data.paymentMethod\n }]]}\n /></div>),\n })}\n >\n <Tag color=\"green\" style={{cursor: \"pointer\"}}>\n ORD-2024-001 - 腾讯科技\n </Tag>\n </TooltipFetch>\n </div>\n </div>\n\n <div>\n <Text strong>库存信息快速查看</Text>\n <div style={{marginTop: 12}}>\n <TooltipFetch\n api={{url: \"/api/product/inventory\"}}\n size=\"large\"\n fetchContent={(data) => ({\n title: \"库存详情\",\n importantInfo: data.available < data.warningLevel ? \"库存不足!当前可用库存低于预警线。\" : null,\n importantInfoType: \"warning\",\n content: (<div style={{width: '500px'}}>\n <Descriptions\n size=\"small\"\n dataSource={[[{label: \"产品编号\", content: data.productId}, {\n label: \"产品名称\", content: data.productName\n }, {label: \"库存总数\", content: data.stock}], [{\n label: \"在途数量\", content: data.inTransit\n }], [{label: \"已预留\", content: data.reserved}, {\n label: \"可用库存\", content: data.available\n }], [{label: \"预警线\", content: data.warningLevel}, {\n label: \"最后更新\", content: data.lastUpdate\n }]]}\n />\n </div>),\n })}\n >\n <Tag color=\"orange\" style={{cursor: \"pointer\"}}>\n 华为Mate 60 Pro - 库存:156\n </Tag>\n </TooltipFetch>\n </div>\n </div>\n\n <div>\n <Text strong>强制刷新数据</Text>\n <div style={{marginTop: 12}}>\n <TooltipFetch\n api={{url: \"/api/employee/detail\"}}\n size=\"large\"\n force={true}\n fetchContent={(data) => ({\n title: \"员工信息(实时数据)\", content: (<div>\n <Text>姓名:{data.name}</Text>\n <br/>\n <Text>部门:{data.department}</Text>\n <br/>\n <Text type=\"secondary\">\n 每次打开都会重新加载数据\n </Text>\n </div>),\n })}\n >\n <Tag color=\"purple\" style={{cursor: \"pointer\"}}>\n 张明(实时数据)\n </Tag>\n </TooltipFetch>\n </div>\n </div>\n </Space>);\n};\n\nrender(<BaseExample/>);\n\n`,\n scope: [{\n name: \"_Tooltip\",\n packageName: \"@components/Tooltip\",\n component: component_113\n},{\n name: \"reactFetch\",\n packageName: \"@kne/react-fetch\",\n component: component_116\n},{\n name: \"_Descriptions\",\n packageName: \"@components/Descriptions\",\n component: component_117\n},{\n name: \"antd\",\n packageName: \"antd\",\n component: component_114\n}]\n}]\n }\n};\nexport default readmeConfig;\n","// extracted by mini-css-extract-plugin\nexport default {\"overlay\":\"style_overlay__ZS5Wz__NN-KB\",\"overlay-content\":\"style_overlay-content__IVFmc__NN-KB\",\"state-tag\":\"style_state-tag__+59RJ__NN-KB\"};","import style from \"./style.module.scss\";\nimport {\n useState, useCallback, useEffect, useRef, useLayoutEffect,\n} from \"react\";\nimport localStorage from \"@common/utils/localStorage\";\nimport StateTag from \"@components/StateTag\";\nimport {Popover, Space} from \"antd\";\nimport dropWhile from \"lodash/dropWhile\";\nimport uniqBy from \"lodash/uniqBy\";\nimport useClickOutside from \"@kne/use-click-outside\";\nimport classnames from \"classnames\";\n\nconst HistoryStore = ({\n className,\n overlayClassName,\n storeName = 'HISTORY_STORE_KEY',\n maxLength = 5,\n label = '最近搜索',\n children,\n onSelect,\n zIndex,\n getPopupContainer,\n }) => {\n const [list, setList] = useState(() => {\n return localStorage.getItem(storeName) || [];\n });\n const [open, setOpen] = useState(false);\n const openHistory = useCallback(() => {\n if (list.length === 0) {\n return;\n }\n setOpen(true);\n }, [list]);\n const storeNameRef = useRef(storeName);\n storeNameRef.current = storeName;\n useEffect(() => {\n localStorage.setItem(storeNameRef.current, list);\n }, [list]);\n\n const appendHistory = useCallback((item) => {\n if (item.value && item.label) {\n setList((list) => {\n const newList = dropWhile(list, {value: item.value});\n newList.splice(0, 0, item);\n return maxLength ? uniqBy(newList, \"value\").slice(0, maxLength) : newList;\n });\n }\n setOpen(false);\n }, [maxLength]);\n\n const close = useCallback(() => {\n setOpen(false);\n }, []);\n\n const outerRef = useClickOutside(close);\n\n const popoverChildrenRef = useRef(null), popoverContentRef = useRef(null);\n outerRef.current = {\n contains: (target) => {\n return (popoverChildrenRef.current.contains(target) || (open && popoverContentRef.current.contains(target)));\n },\n };\n\n const onSelectRef = useRef(null);\n const setOnSelect = (callback) => {\n onSelectRef.current = callback;\n };\n\n const [width, setWidth] = useState(0);\n\n useLayoutEffect(() => {\n const callback = () => {\n setWidth(popoverChildrenRef.current.clientWidth);\n };\n callback();\n const resizeObserver = new ResizeObserver(callback);\n resizeObserver.observe(popoverChildrenRef.current);\n const mutationObserver = new MutationObserver(callback);\n mutationObserver.observe(popoverChildrenRef.current, {\n subtree: true, childList: true,\n });\n return () => {\n mutationObserver.disconnect();\n resizeObserver.disconnect();\n };\n }, []);\n\n return (<Popover\n zIndex={zIndex}\n placement=\"bottom\"\n transitionName={\"ant-slide-up\"}\n arrow={false}\n open={open}\n getPopupContainer={getPopupContainer}\n overlayClassName={classnames(overlayClassName, style[\"overlay\"])}\n content={<div\n className={style[\"overlay-content\"]}\n style={{width}}\n ref={popoverContentRef}\n >\n <Space direction=\"vertical\">\n <div>{label}</div>\n <Space wrap>\n {list.map((item) => (<StateTag\n className={style[\"state-tag\"]}\n text={item.label}\n type={\"result\"}\n onClick={() => {\n onSelect && onSelect(item.value, item);\n onSelectRef.current && onSelectRef.current(item.value, item);\n close();\n appendHistory(item);\n }}\n />))}\n </Space>\n </Space>\n </div>}\n >\n <div ref={popoverChildrenRef} className={classnames(className)}>\n {children({\n open, openHistory, appendHistory, setOnSelect, close,\n })}\n </div>\n </Popover>);\n};\n\nexport default HistoryStore;\n"],"names":["name","summary","api","example","isFull","className","style","list","title","description","code","scope","packageName","importStatement","component","_ref","overlayClassName","storeName","maxLength","label","children","onSelect","zIndex","getPopupContainer","setList","useState","localStorage","getItem","open","setOpen","openHistory","useCallback","length","storeNameRef","useRef","current","useEffect","setItem","appendHistory","item","value","newList","dropWhile","splice","uniqBy","slice","close","outerRef","useClickOutside","popoverChildrenRef","popoverContentRef","contains","target","onSelectRef","width","setWidth","useLayoutEffect","callback","clientWidth","resizeObserver","ResizeObserver","observe","mutationObserver","MutationObserver","subtree","childList","disconnect","_jsx","Popover","placement","transitionName","arrow","classnames","content","ref","_jsxs","Space","direction","wrap","map","StateTag","text","type","onClick","setOnSelect"],"sourceRoot":""}
|