@hw-component/hj
v1.10.94
Published
基于antd二次开发
Readme
@hw-component/hj 组件文档
基于 Ant Design 4.x 二次封装的 React 业务组件库。
环境要求
| 依赖 | 版本 | | --- | --- | | react | 17.0.0 | | react-dom | 17.0.2 | | antd | ^4.20.7 | | @ant-design/icons | 4.6.2 | | ahooks | 2.10.9 | | react-activation | ^0.12.1(使用 HXJ 系列组件时必须) |
快速开始
import React from "react";
import ReactDOM from "react-dom";
import { HJConfigProvider, HJIconSource, HJBody } from "@hw-component/hj";
// 1. 初始化 iconfont 图标源(全局仅需一次)
HJIconSource.create("/fontIcon/iconfont.js");
// 2. (可选)全局配置
ReactDOM.render(
<HJConfigProvider bodyHeight={500}>
<HJBody>内容</HJBody>
</HJConfigProvider>,
document.getElementById("root")
);样式说明
- 样式源码汇总于
src/components/styles/index.less,宿主项目引入该文件(或按组件目录单独引入对应index.less)。 - 所有类名基于 antd 的
prefixCls生成(形如ant-hj-xxx)。若宿主项目通过ConfigProvider修改了 antd 前缀,组件类名会自动跟随,无需额外处理。
全局配置
HJConfigProvider
全局配置容器,内部基于 React Context 实现,可配置项与组件默认配置递归深合并(组件自身传入的 props 优先级更高)。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| bodyHeight | string \| number | - | 全局内容区最小高度,被 HJBody / HXJBody / HJTabPageLayout / HXJTabPageLayout 使用(作为 minHeight) |
| errorPage | ErrorPageConfigModal | - | HJErrorPage 全局配置 |
| emptyPage | EmptyPageConfigModal | - | HJEmptyPage 全局配置 |
interface ErrorPageConfigModal {
image?: string; // 错误页图片
sizeObj?: {
middle?: { height?: number; defaultStyle?: React.CSSProperties };
small?: { height?: number; defaultStyle?: React.CSSProperties };
};
}
interface EmptyPageConfigModal {
bgImgSrc?: string; // 空数据页背景图
imageStyle?: React.CSSProperties; // 图片样式
}HJIconSource
iconfont 图标源管理(单例)。基于 @ant-design/icons 的 createFromIconfontCN 封装。
| 方法/属性 | 类型 | 说明 |
| --- | --- | --- |
| create(scriptUrl, prefix?) | (url: string, prefix?: string) => void | 创建全局图标源,全局只能调用一次,重复调用会告警并忽略 |
| CustomIcon | React.FC | 创建成功后可用的图标组件(一般不直接使用) |
| prefix | string | 图标 type 前缀 |
基础组件
HJSpace 间距容器
对 antd Space 的封装。默认 direction="vertical" 时自动占满宽度(width: 100%),适合表格单元格内的多行信息布局。
<HJSpace size={4}>
<div>第一行</div>
<div>第二行</div>
</HJSpace>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| direction | "vertical" \| "horizontal" | "vertical" | 排列方向 |
| 其余属性 | SpaceProps | - | 透传 antd Space |
HJModal 弹窗
对 antd Modal 的封装。去掉了右上角关闭按钮与底部按钮区,改为底部居中圆形关闭图标,内容区零内边距,适合自定义内容弹窗。
<HJModal visible={visible} onCancel={() => setVisible(false)}>
自定义内容
</HJModal>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| visible | boolean | - | 是否可见 |
| onCancel | () => void | - | 点击底部关闭图标时的回调 |
| 其余属性 | ModalProps | - | 透传 antd Modal(closable、footer、bodyStyle 已被固定) |
HJCard 卡片
对 antd Card 的封装。提供标准化的**页头(title)/内容区/页脚(footer)**三段式结构,title 与 footer 既可以是 ReactNode,也可以是 { text, action, style } 对象(左文案 + 右操作自动两端对齐)。
// 对象写法:左侧标题 + 右侧操作
<HJCard title={{ text: "卡片标题", action: <a>更多</a> }} footer="页脚">
内容
</HJCard>
// headerNoStyle:不套用头部样式,直接渲染原始节点
<HJCard title={<MyHeader />} headerNoStyle>
内容
</HJCard>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | ReactNode \| { text?: ReactNode; action?: ReactNode; style?: CSSProperties } | - | 页头 |
| footer | 同 title | - | 页脚 |
| headerNoStyle | boolean | false | 为 true 时页头不套用默认样式容器 |
| bodyStyle | CSSProperties | - | 内容区样式 |
| 其余属性 | CardProps | - | 透传 antd Card(bodyStyle.padding 固定为 0) |
HJAlert 警告提示
对 antd Alert 的扩展。新增 content / danger 两种业务类型,支持展开/收起长文案。
// danger 类型:使用自定义错误图标与浅橙背景
<HJAlert type="danger" message="错误提示" showIcon />
// 支持展开/收起
<HJAlert
type="content"
message="提示内容"
description={<>很长很长的描述…</>}
showAlert={{ defaultVisible: false }}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| type | AlertProps["type"] \| "content" \| "danger" | - | content 映射为 antd warning(浅橙背景 #FFF7F0);danger 映射为 error(自定义错误图标) |
| showAlert | boolean \| { visible?: boolean; defaultVisible?: boolean; onChange?: (v: boolean) => void } | - | 开启展开/收起功能;受控/非受控均可 |
| 其余属性 | AlertProps | - | 透传 antd Alert(type 除外) |
HJLabel 标题标签
带左侧色条的标题组件,常用于区块标题。支持主标题、副标题、悬浮说明、右侧操作区。
<HJLabel
title="基础信息"
dec="(选填)"
hover={["说明一", "说明二"]}
size="middle"
action={<a>编辑</a>}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | ReactNode | - | 主标题(必填) |
| dec | ReactNode | - | 副标题(secondary 弱化样式) |
| size | "small" \| "middle" \| "lg" | "small" | 字号 |
| hover | string \| string[] | - | 标题旁问号图标的悬浮提示内容(复用 HJTooltip) |
| fontWeight | string \| number | "normal" | 主标题字重 |
| spaceSize | number | 8 | 主标题右侧间距 |
| action | ReactNode | - | 右侧操作区 |
| style | CSSProperties | - | 容器样式 |
HJTooltip 文字提示
对 antd Tooltip 的封装。三种形态:包裹子元素 / 独立问号图标 / 纯图标模式;title 支持数组自动竖排展示。
// 1) 子元素 + 问号图标
<HJTooltip title={["提示一", "提示二"]}>设置</HJTooltip>
// 2) 独立问号图标
<HJTooltip title="说明文案" />
// 3) 无图标纯包裹(icon={false})
<HJTooltip icon={false} title="说明文案"><span>文字</span></HJTooltip>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | string \| string[] \| ReactNode | - | 提示内容;数组时竖排展示 |
| icon | ReactNode \| false | 问号图标 | 自定义提示图标;false 表示不渲染图标(纯包裹模式) |
| iconStyle | CSSProperties | - | 图标样式 |
| iconStopPropagation | boolean | false | 点击图标时是否阻止事件冒泡(表格行内常用) |
| 其余属性 | TooltipProps | - | 透传 antd Tooltip(title 除外) |
HJCopy 复制
点击复制文本,支持单条 / 多条两种形态。多条时以 Link 列表展示并用分隔符隔开,各自独立复制。
// 单条
<HJCopy text="123456">订单号</HJCopy>
// 多条:字符串数组或对象数组
<HJCopy
text={[
{ copyText: "A123", content: "单号A" },
{ copyText: "B456", content: "单号B" },
]}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| text | string \| string[] \| { copyText: string; content: ReactNode; successMsg?: string }[] | - | 待复制内容(必填) |
| separate | ReactNode | "," | 多条之间的分隔符 |
| wrap | boolean | true | 多条是否可换行 |
| label | ReactNode | - | 多条模式下的前置标签 |
| successMsg | string | "复制成功!" | 复制成功提示文案 |
| itemRender | (item) => item | - | 自定义每条 item 的转换逻辑 |
| onClick | (data: string, item) => void | - | 覆盖默认复制行为 |
HJImage 图片
带加载态、空态、悬浮预览的图片容器。支持四种自适应模式(imgMode),其中 fullBody / fullImg 会先加载图片获取真实尺寸,再与容器尺寸比较自动选择铺满方向。
// 固定尺寸 + 悬浮预览
<HJImage width={80} height={80} src={url} />
// 通过请求获取图片地址
<HJImage width={60} request={() => fetchImgUrl()} imgMode={HJImgMode.fullBody} />| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| src | string | - | 图片地址;与 request 二选一 |
| request | () => Promise<string> | - | 异步获取图片地址 |
| width / height | number | - | 容器尺寸;height 缺省时取 width |
| imgMode | HJImgMode | "height" | width:按宽铺满;height:按高铺满;fullBody:图完全在容器内且铺满一边;fullImg:图铺满整个容器(可能裁切) |
| preview | boolean | true | 是否开启悬浮"预览"遮罩(点击打开大图) |
| loading | boolean | - | 外部控制加载态 |
| emptyNode | ReactNode | 内置空图 | 无图时的占位节点 |
| className / style | - | - | 容器样式 |
HJIcon iconfont 图标
渲染通过 HJIconSource.create() 注册的 iconfont 图标。
<HJIconSource.create("/fontIcon/iconfont.js"); />
<HJIcon iconType="edit" onClick={...} />| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| iconType | string | - | 图标名(会自动拼接 HJIconSource.create 时设置的 prefix)(必填) |
| onClick | MouseEventHandler | - | 点击事件 |
| className / style | - | - | 样式 |
| 其余属性 | CustomIconOptions | - | 透传 antd IconFont |
按钮组件
HJBtn 按钮
对 antd Button 的封装。新增 request 能力:传入请求函数后点击自动发起请求并管理 loading,成功后触发 onSuccess;未传 request 时行为同原生按钮。默认圆角 4px。
// 请求按钮:自动 loading
<HJBtn
type="primary"
request={() => api.save()}
onSuccess={() => message.success("保存成功")}
>
保存
</HJBtn>
// 普通按钮
<HJBtn onClick={handleClick}>取消</HJBtn>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| request | () => Promise<any> | - | 点击后自动执行的请求;传入后 onClick 不再生效 |
| onSuccess | (data) => void | - | 请求成功回调 |
| 其余属性 | ButtonProps | - | 透传 antd Button |
HJIconBtn 图标按钮
HJBtn 之上叠加 iconfont 图标 + 文案的组合按钮,图标与文字间距 4。
<HJIconBtn iconType="edit" onClick={...}>
编辑
</HJIconBtn>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| iconType | string | - | HJIcon 图标名 |
| 其余属性 | HJBtnProps | - | 透传 HJBtn |
HJCountdownBtn 倒计时按钮
点击(或请求成功)后进入倒计时禁用状态,结束后恢复。通过 ref 暴露 start / reset。
const ref = useRef<HJCountdownBtnRefModal>(null);
<HJCountdownBtn ref={ref} countdownNum={60} onClick={sendSms}>
发送验证码
</HJCountdownBtn>;
// ref.current.start() 手动开始倒计时| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| countdownNum | number | 10 | 倒计时秒数 |
| countdownRender | (num: number \| null) => ReactNode | 确定 / 确定(Ns) | 按钮文案渲染 |
| ref(HJCountdownBtnRefModal) | { start: () => void; reset: () => void } | - | 命令式控制 |
| 其余属性 | HJBtnProps | - | 透传 HJBtn(内部会透传 onSuccess 驱动倒计时) |
HJPopconfirmBtn 气泡确认按钮
Popconfirm + 按钮的组合。确认后可自动发请求(ok 按钮带 loading),支持完全自定义触发节点。
// 默认形态:link 小按钮
<HJPopconfirmBtn
node="删除"
request={() => api.del(id)}
onSuccess={reload}
/>
// 自定义确认文案 / 位置 / 触发节点
<HJPopconfirmBtn title="确定下架吗?" placement="top" btnProps={{ iconType: "close" }} node="下架" />| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | ReactNode | "删除将无法恢复,确定删除吗?" | 确认提示文案 |
| request | () => Promise<any> | - | 确认后自动执行的请求(ok 按钮自动 loading) |
| onSuccess | (data) => void | - | 请求成功回调 |
| node | ReactNode | - | 按钮内容 |
| btnProps | IconBtnProps | {} | 透传给内部 HJIconBtn / HJBtn;传了 iconType 用图标按钮 |
| render | (loading: boolean) => ReactNode | - | 完全自定义触发节点(优先级最高) |
| 其余属性 | PopconfirmProps | - | 透传 antd Popconfirm(title 除外) |
HJPopCountdown 气泡确认倒计时
PopconfirmBtn 的倒计时版本:气泡展开后确认按钮进入倒计时禁用,收起即重置。适用于"高风险操作需阅读"场景。
<HJPopCountdown
node="删除"
countdownNum={5}
request={() => api.del(id)}
onSuccess={reload}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| countdownNum | number | 10 | 确认按钮倒计时秒数 |
| countdownRender | (num: number \| null) => ReactNode | 确定 / 确定(Ns) | 确认按钮文案 |
| onVisibleChange | (visible: boolean) => boolean \| Promise<boolean> | - | 返回 false 可拦截气泡显隐 |
| 其余属性 | HJPopconfirmBtnProps | - | 透传 HJPopconfirmBtn |
HJOperateBtn 操作按钮组
表格"操作"列标准组件。根据 config 渲染一组 link 小按钮,项之间自动加竖线分隔符;支持按行数据动态显隐、删除类操作自动套 Popconfirm、按钮级请求。
<HJOperateBtn
data={record} // 行数据,传给 show / request / onClick
config={[
{ key: "edit", node: "编辑", show: (data) => data.canEdit },
{ key: "del", node: "删除", delTips: true, placement: "top" },
{ key: "copy", node: "复制", noBtn: true }, // node 自渲染,不加按钮样式
]}
onClick={(key, data) => {
if (key === "edit") openModal(data);
}}
requestConfig={{ del: (data) => api.del(data.id) }}
onSuccess={reload}
/>config 项(ConfigModal):
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| node | ReactNode | 按钮内容(必填) |
| key | string | 唯一标识,onClick / requestConfig 依据 |
| delTips | string \| boolean | 传 true 用默认删除确认语;传字符串自定义;配置后自动套 Popconfirm |
| show | boolean \| (data) => boolean | 动态显隐 |
| placement | TooltipPlacement | Popconfirm 弹出位置 |
| noBtn | boolean | 为 true 时不套按钮样式,直接 clone node 并注入 btnStyle(用于嵌套 DropdownBtn 等) |
组件 props(HJOperateBtnProps):
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | ConfigModal[] | - | 按钮配置(必填) |
| data | Record<string, any> | {} | 行数据 |
| onClick | (key, data) => void | - | 无 request 时的点击回调 |
| requestConfig | Record<string, (data) => Promise> | {} | 按 key 配置按钮请求,确认后自动执行并 loading |
| onSuccess | () => void | - | 任一请求成功回调 |
| hr | boolean | true | 按钮间是否显示竖线分隔 |
| containerRender | (node, config) => ReactNode | - | 包裹每个按钮的自定义渲染(如套 Tooltip) |
| emptyNode | ReactNode | "-" | 过滤后无按钮时的占位 |
HJOperateBtnMaxCount 限额操作按钮组
HJOperateBtn 的数量上限版本:可见按钮超过 maxCount 时,前 maxCount - 1 个正常展示,剩余收进"更多"下拉(内部使用 HJDropdownBtn,delTips 转为 confirmText)。
<HJOperateBtnMaxCount
maxCount={3}
actionNode="更多"
data={record}
config={[{ key: "a", node: "操作A" }, ...]}
requestConfig={{ a: (data) => api.a(data.id) }}
onSuccess={reload}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| maxCount | number | - | 最大可见按钮数(含"更多") |
| config | CountConfigModal[] | - | 同 HJOperateBtn 的 config |
| actionNode | ReactNode | - | "更多"下拉触发按钮文案 |
| actionPosition | OperateBtnPosition | end | "更多"收起位置:start(第一位)/ end(最后一位) |
| 其余属性 | HJOperateBtnProps | - | 透传 HJOperateBtn |
HJDropdownBtn 下拉操作按钮
表格"操作"列下拉形态。菜单项支持二级嵌套、按行数据显隐、点击直接执行请求、确认弹窗(confirmText)与确认倒计时(countdown)。
<HJDropdownBtn
data={record}
config={[
{ key: "edit", label: "编辑" },
{
key: "more",
label: "更多",
children: [
{ key: "del", label: "删除", confirmText: "删除后无法恢复", countdown: 3, request: (d) => api.del(d.id) },
],
},
]}
onClick={(checkData, data) => console.log(checkData.key, data)}
onSuccess={reload}
/>config 项(DropdownBtnConfigData):
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| label | ReactNode | 菜单名(必填) |
| key | string | 唯一标识(必填) |
| children | DropdownBtnConfigData[] | 二级菜单 |
| show | (data) => boolean | 动态显隐(注意:接收的是整个 config 数据) |
| confirmText | ReactNode | 配置后点击弹出确认弹窗 |
| countdown | number | 确认弹窗确定按钮的倒计时秒数 |
| request | (data) => Promise | 点击(确认后)自动执行的请求 |
组件 props(HJDropdownBtnProps):
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | DropdownBtnConfigData[] | - | 菜单配置(必填) |
| data | T | - | 行数据,传给 request / onClick |
| onClick | (checkData: { key, keyPath }, data) => void | - | 无 request/confirmText 项的点击回调 |
| requestConfig | Record<string, (params) => Promise> | {} | 按 key 集中配置请求(与 config.request 二选一,支持嵌套对象按层级配置) |
| onSuccess | () => void | - | 请求成功回调 |
| btnStyle | CSSProperties | - | 触发按钮样式 |
| hideIcon | boolean | - | 隐藏默认的下拉箭头 |
| arrow | boolean | true | 下拉箭头(antd) |
| emptyNode | ReactNode | "-" | 菜单为空时的占位 |
| 其余属性 | DropdownProps | - | 透传 antd Dropdown(overlay 除外) |
布局组件
HJBody 页面容器
标准页面容器:操作区(action)+ 内容区 + 底部区(footer),内容区自动接管 loading / error / 空数据状态(内部使用 HJLoadingHandler)。高度自动应用 HJConfigProvider.bodyHeight(作为 minHeight)。
<HJBody
action={<Space>...筛选区</Space>}
footer={<HJAffixFooter />}
loadingHandler={{ loading, error, data, reload }}
>
<Table ... />
</HJBody>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| action | ReactNode | - | 顶部操作区(自带底部内边距) |
| footer | ReactNode | - | 底部区域 |
| noPadding | boolean | false | 内容区去除内边距 |
| bodyStyle | CSSProperties | - | 内容区样式 |
| actionStyle | CSSProperties | - | 操作区样式 |
| loadingHandler | LoadingHandlerProps | - | 内容区状态配置(loading/error/data 等,见 HJLoadingHandler) |
| className / style | - | - | 容器样式 |
HXJBody 页面容器(留白变体)
HJBody 的变体,类名与默认留白不同:noPadding 时内容区上下留白 20px、操作区去除内边距,适合内嵌 Tab 等场景。
<HXJBody noPadding footer={...}>
<SourceTabBar />
</HXJBody>Props 同 HJBody。
HJTabPage 页签页容器
Body + Tabs 的组合:顶部 antd Tabs 页签,外层带 action / footer 插槽。
<HJTabPage
config={[
{ key: "base", label: "基础设置", node: <BasePanel /> },
{ key: "adv", label: "高级设置", node: <AdvPanel />, forceRender: true },
]}
footer={<HJAffixFooter />}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | ConfigModal[] | - | 页签配置(必填) |
| contentNoPd | boolean | - | 内容区去除内边距 |
| forceRender | boolean | - | 所有面板默认预渲染 |
| 其余属性 | TabsProps | - | 透传 antd Tabs |
config 项(ConfigModal,HJBody 系列通用):
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| node | ReactNode | 面板内容(必填) |
| label | ReactNode | 页签名(必填) |
| key | string | 唯一标识,缺省取索引 |
| forceRender | boolean | 预渲染 |
HXJTabPage 页签页容器(留白变体)
HJTabPage 的变体(内部使用 HXJBody),适合内嵌在其它容器中的二级页签。
Props 同 HJTabPage。
HJTabPageLayout 侧边页签布局
左侧菜单 + 右侧内容的双栏布局。面板用 react-activation 的 KeepAlive 缓存,切换页签不丢状态;卸载时自动清理缓存,通过 ref 可手动刷新缓存。
const ref = useRef<HJTabPageLayoutRef>(null);
<HJTabPageLayout
ref={ref}
config={[
{ key: "base", label: "基础设置", node: <BasePanel /> },
{ key: "adv", label: "高级设置", node: <AdvPanel />, noPd: true },
]}
activeKey={key}
onChange={setKey}
action={<Breadcrumb />}
footer={<HJAffixFooter />}
/>;
// ref.current.refresh() 手动刷新当前缓存| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | ConfigModal[] | - | 页签配置(同上,另支持 noPd、bodyStyle) |
| activeKey | string | 首项 | 受控选中 key |
| onChange | (key: string) => void | - | 切换回调(受控模式必传) |
| action | ReactNode | - | 顶部操作区 |
| footer | ReactNode | - | 底部区域 |
| contentNoPd | boolean | - | 所有内容区去内边距 |
| menuStyle | CSSProperties | - | 左侧菜单样式 |
| className / style | - | - | 容器样式 |
| ref(HJTabPageLayoutRef) | { refresh: () => void } | - | 刷新 KeepAlive 缓存 |
HXJTabPageLayout 侧边页签布局(增强版)
在 HJTabPageLayout 基础上增强:菜单搜索、拖拽排序、菜单项自定义渲染(编辑/删除),config 支持受控更新。适合"自定义工作台页签"场景。
<HXJTabPageLayout
drag
config={config}
onChange={setConfig} // 受控:拖拽/删除/编辑后回传新 config
menuItemRender={({ data, dragNode, del, edit, actived }) => (
<div onClick={del}>...</div>
)}
searchRender={(inputNode, onSearch) => inputNode}
activeChange={(key) => ...}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | TabPageLayoutConfig[](label 为 string) | - | 页签配置,支持受控 |
| onChange | (config) => void | - | config 变更回调(拖拽排序/删除/编辑时触发) |
| activeKey | string | 首项 | 受控选中 key |
| activeChange | (key: string) => void | - | 切换回调(与 onChange 职责分离) |
| drag | boolean | - | 开启菜单拖拽排序 |
| menuItemRender | (params: { data; dragNode; del: (index) => void; edit: (index, patch) => void; actived }) => ReactNode | - | 自定义菜单项渲染;del/edit 由组件提供 |
| searchRender | (inputNode, onSearch) => ReactNode | - | 菜单搜索区渲染(按 label 过滤) |
| emptyMenuRender | (emptyNode) => ReactNode | - | 菜单为空时渲染 |
| emptyContentRender | (emptyNode) => ReactNode | - | 内容区为空时渲染 |
| footer | ReactNode | - | 底部区域 |
| contentNoPd | boolean | - | 内容区去内边距 |
| ref(HJTabPageLayoutRef) | { refresh: () => void } | - | 刷新 KeepAlive 缓存 |
注意:del 删除项时会同步清理对应 KeepAlive 缓存,若删除的是当前激活项会自动切换到相邻项。
HJAffixSource 底部吸附容器
对 antd Affix 的封装:吸底时自动切换为全宽白色带阴影样式。
<HJAffixSource target={() => window} affixedStyle={{ padding: 16 }}>
自定义底部内容
</HJAffixSource>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| hideAffix | boolean | - | 为 true 时不吸附,直接渲染 |
| affixedStyle | CSSProperties | - | 吸附后的样式 |
| safeNoShadow | boolean | - | 未吸附时是否去除阴影 |
| target | () => HTMLElement | window | 滚动容器(antd) |
| 其余属性 | AffixProps | - | 透传 antd Affix |
HJAffixFooter 底部吸附保存栏
吸附容器 + 提示文案 + 保存按钮的标准组合。
<HJAffixFooter message="设置完成,记得保存哦!" btnProps={{ request: save, onSuccess }} />
// 或完全自定义按钮
<HJAffixFooter btnNode={<MyBtn />} />| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| message | string | "设置完成,记得保存哦!" | 左侧提示文案,传空串隐藏 |
| icon | ReactNode | - | 提示文案前图标 |
| btnNode | ReactNode | 默认保存按钮 | 完全自定义右侧按钮 |
| btnProps | HJBtnProps | - | 默认保存按钮的 props(type 默认 primary) |
| 其余属性 | HJAffixProps | - | 透传 HJAffixSource |
页面状态组件
HJShowChild 条件渲染
最简单的显隐容器,常用于动态插槽。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| show | boolean | - | 为 true 时渲染 children |
HJPageLoading 加载中
带遮罩的全页加载容器。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| spinning | boolean | - | 显示加载遮罩 |
| tip | string | "拼命加载中..." | 加载文案 |
| loadingStyle | CSSProperties | - | 遮罩样式(如背景色) |
| wrapperClassName / style | - | - | 容器样式 |
| 其余属性 | SpinProps | - | 透传 antd Spin |
HJLoadingHandler 页面状态处理
页面加载/错误/空数据三态自动切换的标准容器(loading 遮罩 + 错误页 + 空数据占位)。
<HJLoadingHandler loading={loading} error={error} data={data} reload={reload}>
<Table dataSource={list} />
</HJLoadingHandler>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| loading | boolean | false | 加载中 |
| error | Error | - | 错误对象(展示 error.message 与刷新按钮) |
| data | any | - | 业务数据,空值时按空数据处理 |
| reload / run | () => void | - | 错误页"刷新"按钮回调 |
| loadingHideInData | boolean | - | 有数据时隐藏 loading 遮罩(避免遮挡列表) |
| noDataEmpty | boolean | true | 无数据时是否渲染空占位(高度 368 的空白块) |
| destroyOnLoading | boolean | false | 加载中是否卸载 children |
| loadingStyle / errorStyle / style | CSSProperties | - | 各区域样式 |
HJAutoPageHandler 请求页面容器
"请求 + 三态处理 + 页面容器"一体化:内部用 ahooks useRequest 发起请求,自动接管 loading/error/data,外层套 HJBody。
<HJAutoPageHandler
request={() => api.getDetail(id)}
options={{ refreshDeps: [id] }}
render={({ data, reload }) => (
<Detail data={data} onSaved={reload} />
)}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| request | (...args) => Promise<R> | - | 请求函数(必填) |
| render | (result: { data; reload }) => ReactNode | - | 内容渲染(必填);reload 即重新请求 |
| options | BaseOptions | - | ahooks useRequest 配置 |
| bodyProps | HJBodyProps | {} | 透传 HJBody |
| noWrapper | boolean | - | - |
| 其余属性 | LoadingHandlerProps | - | 透传 HJLoadingHandler |
HJSkeletonLoading 骨架屏容器
加载中显示骨架屏,有数据渲染内容,出错显示错误页。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| data | any | - | 业务数据(必填) |
| loading | boolean | - | 加载中 |
| error | Error | - | 错误对象 |
| reload | () => void | - | 错误页刷新回调 |
| 其余属性 | SkeletonProps | - | 透传 antd Skeleton |
HJEmptyPage 空数据页
基于 antd Empty 的空数据页,支持通过 HJConfigProvider.emptyPage 全局定制背景图与尺寸。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| description | string | "暂无数据~" | 描述文案 |
| bgImgSrc | string | 内置背景图 | 背景图(可全局配置) |
| imageStyle | CSSProperties | { height: 167 } | 图片样式(可全局配置) |
| className / style | - | - | 容器样式 |
HJEmptyPageHandler 空数据处理器
isEmpty 为 true 时渲染 HJEmptyPage,否则渲染 children。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| isEmpty | boolean | - | 是否为空 |
| 其余属性 | IEmptyPageProps | - | 透传 HJEmptyPage |
HJErrorPage 错误页
错误信息 + 刷新按钮的标准错误页,支持通过 HJConfigProvider.errorPage 全局定制图片与尺寸。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| error | Error | - | 错误对象,message 作为描述(必填) |
| reload | () => void | - | 刷新按钮回调 |
| size | "middle" \| "small" | "middle" | 尺寸(决定图片高度与留白) |
| style | CSSProperties | - | 容器样式 |
页签组件
HJBtnTab 按钮组页签
Radio.Button 风格的页签切换(按钮组形态),面板复用 antd Tabs 渲染。
<HJBtnTab
config={[
{ key: "day", label: "日榜", node: <DayTable /> },
{ key: "week", label: "周榜", node: <WeekTable /> },
]}
activeKey={key}
onChange={setKey}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | { label; key?; node?; forceRender? }[] | - | 页签配置(必填) |
| activeKey | string | 首项 | 受控选中 key |
| defaultActiveKey | string | 首项 | 初始选中 key |
| onChange | (key: string) => void | - | 切换回调(受控模式必传) |
| tabBarStyle | CSSProperties | - | 按钮组容器样式 |
| bodyNoPd | boolean | - | 内容区去内边距 |
HJBtnTabBar 按钮组页签栏
HJBtnTab 的按钮组部分(不含面板),用于自定义面板场景。
Props 同 HJBtnTab(仅渲染按钮组)。
表格业务渲染组件(HJTableRender)
电商/订单类后台表格的标准单元格渲染器。
HJProductMsg 商品信息
商品图 + 标题(可链接、溢出提示)+ 店铺/付费信息 + 来源图标组(Tooltip 说明)+ 底部插槽。
<HJProductMsg
img={record.img}
link={record.url}
title={record.title}
shopName={record.shopName}
payNum={record.payNum}
sourceIcons={[SourceIconType.tm, SourceIconType.jhs]}
footer={<div>...</div>}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | string | - | 商品标题(必填),溢出省略 + 悬浮全文 |
| img | string | 内置占位图 | 商品图 |
| link | string | - | 标题跳转链接(新窗口) |
| shopName | string | - | 店铺名(溢出省略) |
| payNum | string \| null | - | 付费金额,渲染为 付费:¥xx;传 null 不渲染 |
| sourceIcons | SourceIconType[] | - | 来源图标组,枚举见下 |
| content | ReactNode | - | 覆盖默认的店铺/付费信息区域 |
| footer | ReactNode | - | 底部插槽 |
SourceIconType 枚举(28 项,含图标与内置提示语):app、superRed(超红)、cms、directional(定向)、elm(饿了么)、fliggy(飞猪)、officialAccount(公众号)、group(社群发单)、jhs(聚划算)、pcRobot / androidRobot / pcEnterpriseRobot / ipadRobot(各类机器人)、kill(杀熟)、freeOrder(免单)、crossStore(跨店)、tb(淘宝)、tbSpecialOffer(淘宝特价)、there(三方)、recommend(推荐)、sameStore(同店)、tm(天猫)、tmgj(天猫国际)、wxPyq(微信朋友圈)、minApp(小程序)、dy(抖音)、dyGroup(抖团)、ks(快手)、pdd(拼多多)、vph(唯品会)、jd(京东)。
HJSingleProductMsg 商品信息(精简)
仅图 + 标题(点击跳转)的精简版。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| title | string | - | 标题(必填) |
| img | string | 内置占位图 | 商品图 |
| link | string | - | 点击图/标题新窗口打开 |
HJProductSourceMsg 佣金信息渲染器
通用两列布局渲染器:将 config 按每行 2 项切分,项间竖线分隔,key 交给 render 产出节点。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| config | { key: string; node?: ReactNode }[] | - | 渲染项;有 node 用 node,否则调 render(必填) |
| render | (key: string) => ReactNode | - | 按 key 渲染内容(必填) |
HJProductRebateMsg 佣金信息(标准)
收入 / 提成 / 买家收入 / 利润(正绿负红)/ 其他(可展开下拉明细)五项,每行 2 项布局。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| income | number | - | 收入:¥xx |
| commission | number | - | 提成:xx% |
| buyIncome | number | - | 买家:¥xx |
| profit | number | - | 利润:¥xx(>0 绿色,<0 红色) |
| other | number | - | 其他:¥xx(配合 dropdownConfig 可展开明细) |
| dropdownConfig | { label: string; key?: string }[] | - | “其他”下拉明细 |
| render | (key, node) => ReactNode | 原样返回 | 每项内容的二次包装 |
HJTCRebate 佣金信息(团长)
团长版:收入 / 买家收入 / 利润 / 其他 四项。Props 同 HJProductRebateMsg。
HJProductVphRebateMsg 佣金信息(唯品会)
唯品会版:收入 / 提成 / 买家 / 礼金支出 / 补贴 / 利润 / 其他 七项。在标准版基础上新增:
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| vphReward | number | - | 礼金支出:¥xx |
| 其余 | HJProductRebateProps | - | 同标准版(另渲染补贴 subsidyCommission) |
HJDUMsg / HJDUMsgHideRemark 用户信息
表格中"用户/推广者"单元格:名字 + 备注 + ID 复制。HJDUMsgHideRemark 不展示备注。
<HJDUMsg id={record.duId} name={record.duName} remark={record.remark} onClick={...} />| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| id | string | - | 用户 ID(必填),展示为可复制链接 |
| name | string | - | 名字,缺省 - |
| remark | string | - | 备注,缺省 -(仅 HJDUMsg) |
| onClick | () => void | - | 名字点击回调 |
HJRowMsg 多行文本
多个字符串竖排展示,空值补 -。
| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| text | string[] | - | 文本数组(必填) |
拖拽排序组件(HJSortComponent)
基于 react-sortable-hoc 封装的列表拖拽排序方案。
HJSortContainer 拖拽排序容器
受控数据驱动:拖拽结束自动计算新顺序并回调 onChange;render 内提供每项的 add / del 增删能力。
<HJSortContainer
data={list}
onChange={setList}
render={({ data, index, add, del }) => (
<div>
<HJDragHandle>拖拽把手</HJDragHandle>
{data.name}
<a onClick={() => add({ id: Date.now(), name: "新项" })}>插入</a>
<a onClick={() => del()}>删除</a>
</div>
)}
/>| Prop | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| data | T[] | - | 列表数据(必填);建议每项含 id 作为 key |
| render | (params: { data: T; index: number; add: (value, index?) => void; del: (index?) => void }) => ReactNode | - | 每项渲染(必填);add 默认插到当前项之后,del 默认删除当前项 |
| onChange | (data: T[]) => void | - | 排序/增删后的新数据回调 |
| sortableItemProps | { style?: CSSProperties } | - | 每项包裹层样式 |
| 其余属性 | SortableContainerProps | - | 透传 react-sortable-hoc(如 useDragHandle、helperClass、onSortEnd) |
HJSortableItem 可排序项
被 SortableElement 包裹的项容器(HJSortContainer 内部已使用,一般不单独使用)。
HJDragHandle 拖拽把手
被 SortableHandle 包裹的把手容器。配合容器的 useDragHandle 使用,可实现"仅把手可拖拽"。
<HJSortContainer useDragHandle ... render={({ data }) => (
<HJDragHandle style={{ cursor: move}}>{data.name}</HJDragHandle>
)} />