@kordar/easyui
v2.0.3
Published
基于 React 18 + rc-easyui 的企业级 UI 组件封装库,提供布局、表单、数据网格、消息通知、抽屉、卡片等开箱即用的组件。
Readme
EasyUI
基于 React 18 + rc-easyui 的企业级 UI 组件封装库,提供布局、表单、数据网格、消息通知、抽屉、卡片等开箱即用的组件。
安装
npm install rc-easyui快速开始
import React from 'react';
import { AdminLayout, DrawerPanel, Card, $toast } from 'easyui';
function App() {
return (
<AdminLayout
collapsed={false}
logo="/logo.png"
title="管理系统"
menus={menuData}
slots={{ userPanel: <UserMenu /> }}
>
<Card title="欢迎">
<p>内容区域</p>
</Card>
</AdminLayout>
);
}CSS 主题系统
主题目录结构
public/themes/
├── cartoon/ ← 卡通主题(推荐)
│ ├── easyui.css ← 主样式(自包含所有组件)
│ ├── dark.css ← Dark 模式覆盖
│ ├── drawer.css ← 抽屉独立样式
│ ├── card.css ← 卡片独立样式
│ ├── color.css ← 调色板颜色类
│ └── images/ ← 精灵图资源
├── green/ ← 绿色主题
├── government-blue/ ← 政务蓝主题
└── tech-blue/ ← 科技蓝主题CSS 变量体系
所有主题通过 CSS 变量控制视觉风格。覆盖这些变量即可定制主题:
| 变量 | 说明 | cartoon 浅色默认值 |
|------|------|-------------------|
| --generated-background | 页面背景色 | #FAFAFA |
| --generated-foreground | 主文字色 | #212121 |
| --generated-card | 卡片/面板背景 | #FFFFFF |
| --generated-card-foreground | 卡片文字色 | #212121 |
| --generated-primary | 主强调色(按钮、链接) | #FF9800 |
| --generated-primary-foreground | 主色上的文字 | #FFFFFF |
| --generated-secondary | 次要色 | #FFE5B4 |
| --generated-secondary-foreground | 次要色上的文字 | #212121 |
| --generated-muted | 弱化背景 | #FFF5E6 |
| --generated-muted-foreground | 弱化文字 | #757575 |
| --generated-accent | 强调背景 | #FFF5E6 |
| --generated-accent-foreground | 强调文字 | #212121 |
| --generated-border | 边框色 | #FFE0B2 |
| --generated-input | 输入框边框 | #FFE0B2 |
| --generated-ring | 聚焦环颜色 | #FF9800 |
| --generated-destructive | 危险/错误色 | #FF8A80 |
| --generated-success | 成功色 | #66BB6A |
| --generated-info | 信息色 | #4FC3F7 |
| --generated-radius | 全局圆角 | .5rem |
| --generated-shadow-card | 卡片阴影 | 0 2px 8px rgba(...), 0 4px 16px rgba(...) |
| --generated-shadow-hover | hover 阴影 | 0 4px 16px rgba(...) |
侧边栏变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| --generated-sidebar-background | 侧边栏背景 | #FFF3E0 |
| --generated-sidebar-foreground | 侧边栏文字 | #212121 |
| --generated-sidebar-accent | 侧边栏高亮背景 | #FFE0B2 |
| --generated-sidebar-accent-foreground | 侧边栏高亮文字 | #E65100 |
| --generated-sidebar-border | 侧边栏边框 | #FFF3E0 |
Dark 模式下的交互状态变量
| 变量 | 说明 |
|------|------|
| --generated-hover-surface | hover 背景 |
| --generated-hover-surface-soft | hover 柔化背景 |
| --generated-hover-border | hover 边框 |
| --generated-hover-outline | hover 外轮廓 |
| --generated-hover-shadow | hover 内阴影 |
| --generated-selected-surface | 选中背景 |
| --generated-selected-surface-strong | 选中强背景 |
| --generated-selected-foreground | 选中文字 |
| --generated-selected-shadow | 选中阴影 |
| --generated-disabled-surface | 禁用背景 |
| --generated-disabled-border | 禁用边框 |
| --generated-disabled-foreground | 禁用文字 |
| --generated-button-shadow | 按钮阴影 |
| --generated-button-shadow-soft | 按钮柔化阴影 |
Drawer 变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| --drawer-bg | 抽屉背景 | #FFFFFF |
| --drawer-mask-bg | 遮罩背景 | rgba(0,0,0,0.3) |
| --drawer-border | 抽屉分割线 | rgba(255,224,178,0.48) |
| --drawer-duration | 动画时长 | 0.25s |
| --drawer-header-bg | 头部背景 | gradient |
| --drawer-footer-bg | 底部背景 | rgba(255,243,224,0.7) |
| --drawer-close-hover-bg | 关闭按钮 hover | rgba(255,152,0,0.12) |
布局变量
| 变量 | 说明 | 默认值 |
|------|------|--------|
| --main-body-header-padding | 主内容区顶部 padding | 0 24px |
| --main-body-content-padding | 主内容区主体 padding | 24px |
| --main-body-footer-padding | 主内容区底部 padding | 0 24px |
颜色工具类
/* 状态色 */
.k-color-warn /* 警告 */
.k-color-success /* 成功 */
.k-color-info /* 信息 */
.k-color-error /* 错误 */
.k-color-alert /* 告警 */
.k-color-question/* 疑问 */
/* 调色板(140+ 色) */
.color-red
.color-orange
.color-blue
.color-green
.color-purple
/* ... 更多见 color.css */Dark 模式
<!-- 在 html 标签上添加 dark 类即可启用 -->
<html class="dark">/* dark 模式自动覆盖 CSS 变量 */
html.dark {
--generated-background: #211c1a;
--generated-foreground: #eadfd6;
--generated-primary: #f2a65a;
/* ... */
}组件 API
布局组件
AdminLayout / FullBodyLayout
企业级后台管理布局,含侧边栏、顶栏、主内容区、底栏。
import { AdminLayout } from 'easyui';| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| children | ReactNode | — | 主内容区 |
| collapsed | boolean | — | 侧边栏折叠状态 |
| logo | string | — | Logo 图片地址 |
| title | string | — | 系统标题 |
| headerHeight | number | 60 | 顶栏高度(px) |
| footerHeight | number | 60 | 底栏高度(px) |
| menus | Array | — | 侧边菜单数据 |
| selection | object | — | 当前选中菜单项 |
| sidebarCfg | object | — | 侧边栏额外配置 |
| slots | object | — | 插槽(见下方) |
| toggle | (collapsed: boolean) => void | — | 折叠切换回调 |
| onSideMenuSelection | (selection) => void | — | 菜单选中回调 |
slots 插槽:
slots={{
barLeft: <div/>, // 顶栏左侧
barRight: <div/>, // 顶栏右侧
title: <div/>, // 标题区域
userPanel: <div/>, // 用户面板
footer: <div/>, // 底栏
mainHeader: <div/>, // 主内容区头部
mainFooter: <div/>, // 主内容区尾部
}}DefaultPanel
标准面板容器,支持 header/footer。
import { DefaultPanel } from 'easyui';
<DefaultPanel
mode="cover"
header={<h3>标题</h3>}
footer={<button>确定</button>}
>
<p>内容</p>
</DefaultPanel>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| children | ReactNode | — | 面板内容 |
| mode | 'cover' \| 'none' | 'none' | 内容渲染模式 |
| header | Function | — | 头部内容 |
| footer | Function | — | 底部内容 |
Card
信息卡片容器,支持标题、图标、底部操作区。
import { Card } from 'easyui';
<Card
title="用户信息"
icon="icon-user"
footer={<button>编辑</button>}
colSpan={2}
>
<p>张三 | [email protected]</p>
</Card>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | ReactNode | — | 卡片标题 |
| icon | string | — | 标题图标(iconfont class) |
| children | ReactNode | — | 内容 |
| content | ReactNode | — | 内容(与 children 二选一) |
| footer | ReactNode | — | 底部操作区 |
| colSpan | number | 1 | 网格列跨度 |
| className | string | '' | 自定义类名 |
| style | CSSProperties | {} | 自定义样式 |
TabsPanel
多标签页切换容器(基于 rc-easyui Tabs)。
import { TabsPanel } from 'easyui';
const tabs = [
{ id: 1, title: '标签1', path: '/tab1', closable: true, type: 'page' },
{ id: 2, title: '标签2', path: '/tab2', closable: true, type: 'page' },
];
<TabsPanel
data={tabs}
onTabSelect={(tab) => console.log(tab)}
onTabClosed={(tab) => console.log('closed', tab)}
/>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| data | TabPanelItem[] | — | 标签数据列表 |
| tabsCfg | object | {} | rc-easyui Tabs 配置透传 |
| tabPanelCfg | object | {} | rc-easyui TabPanel 配置透传 |
| onTabSelect | (tab) => void | — | 标签选中回调 |
| onTabClosed | (info) => void | — | 标签关闭回调 |
TabPanelItem 结构:
interface TabPanelItem {
id: string | number;
title: string;
path: any;
closable: boolean;
type: string | number;
}Breadcrumb
面包屑导航。
import { Breadcrumb } from 'easyui';
const items = [
{ label: '首页', path: '/home' },
{ label: '用户管理', path: '/users' },
{ label: '用户详情' },
];
<Breadcrumb
items={items}
hasBack
toBack={() => history.back()}
to={(item) => navigate(item.path)}
separator="/"
/>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| items | BreadcrumbItem[] | — | 面包屑数据 |
| hasBack | boolean | — | 是否显示返回按钮 |
| backLabel | string | 'Back' | 返回按钮文字 |
| separator | string | '/' | 分隔符 |
| toBack | () => void | — | 返回回调 |
| to | (item, e) => void | — | 点击项回调 |
BreadcrumbItem 结构:
interface BreadcrumbItem {
label: string;
path?: any; // 有值则显示为链接
iconCls?: string; // 图标类名
separator?: string; // 该项后的分隔符(覆盖全局)
}抽屉组件
DrawerPanel
侧边抽屉面板,支持四级方向、多尺寸、ESC 关闭、销毁机制。
import { DrawerPanel, useRef } from 'easyui';
const drawerRef = useRef();
// 通过 ref 控制
drawerRef.current?.open();
drawerRef.current?.close();
drawerRef.current?.toggle();
<DrawerPanel
ref={drawerRef}
placement="right"
size="default"
title="编辑信息"
closable
keyboard
destroyOnClose
footer={
<>
<button onClick={() => drawerRef.current?.close()}>取消</button>
<button>保存</button>
</>
}
afterOpenChange={(open) => console.log(open)}
onClose={() => console.log('closed')}
>
<p>抽屉内容</p>
</DrawerPanel>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| title | ReactNode | — | 抽屉标题 |
| placement | 'left' \| 'right' \| 'top' \| 'bottom' | 'right' | 弹出方向 |
| size | 'small' \| 'default' \| 'large' \| string | — | 预设尺寸/自定义宽度 |
| width | string | — | 自定义宽度(覆盖 size) |
| height | string | — | 自定义高度(用于 top/bottom) |
| closable | boolean | true | 是否显示关闭按钮 |
| destroyOnClose | boolean | true | 关闭后销毁内容 |
| keyboard | boolean | true | ESC 键关闭 |
| footer | ReactNode | — | 底部操作区 |
| afterOpenChange | (open: boolean) => void | — | 打开/关闭回调 |
| onClose | () => void | — | 关闭回调 |
| children | ReactNode | — | 内容 |
预设尺寸:
| size | 宽度 |
|------|------|
| small | 320px |
| default | 480px |
| large | 720px |
表单组件
CheckboxGroupBox
复选框组,支持双向绑定。
import { CheckboxGroupBox } from 'easyui';
<CheckboxGroupBox
options={[
{ value: 'a', text: '选项A' },
{ value: 'b', text: '选项B' },
]}
values={['a']}
onChange={(value, checked, newValues) => console.log(newValues)}
/>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| options | CheckboxOption[] | — | 选项列表 |
| values | (string\|number)[] | — | 当前选中值 |
| name | string | 'checkbox-group' | 表单 name |
| onChange | (value, checked, newValues) => void | — | 值变化回调 |
| style | CSSProperties | — | 容器样式 |
| itemStyle | CSSProperties | — | 单项样式 |
CheckboxOption 结构:
interface CheckboxOption {
value: string | number;
text: string;
}RadioGroupBox
单选框组。
import { RadioGroupBox } from 'easyui';
<RadioGroupBox
options={[
{ value: 1, text: '男' },
{ value: 2, text: '女' },
]}
value={1}
onChange={(value) => console.log(value)}
/>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| options | RadioOption[] | — | 选项列表 |
| value | string\|number | — | 当前选中值 |
| name | string | 'radio-group' | 表单 name |
| onChange | (value, checked) => void | — | 选中回调 |
| style | CSSProperties | — | 容器样式 |
| itemStyle | CSSProperties | — | 单项样式 |
Access
权限控制组件,根据权限点控制子元素显示。
import { Access } from 'easyui';
<Access ctx={authCtx} point="user:edit">
<button>编辑用户</button>
</Access>| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| children | ReactNode | — | 受控内容 |
| ctx | { can(point: string): boolean } | — | 权限上下文 |
| point | string | — | 权限点标识 |
数据网格 HOC
withCheckGrid
为 DataGrid 添加复选框列。
import { withCheckGrid } from 'easyui';
import { DataGrid } from 'rc-easyui';
const CheckDataGrid = withCheckGrid(DataGrid);
<CheckDataGrid
data={rows}
selectedRows={[]}
onSelectionChange={(rows) => console.log(rows)}
/>withRadioGrid
为 DataGrid 添加单选框列。
import { withRadioGrid } from 'easyui';
const RadioDataGrid = withRadioGrid(DataGrid);消息通知
$toast
轻量级消息提示,自动消失。
import { $toast } from 'easyui';
$toast.info('操作成功');
$toast.success('保存成功', 5000);
$toast.warning('请注意');
$toast.error('操作失败');| 方法 | 参数 | 说明 |
|------|------|------|
| $toast.info(content, timeout?) | 内容, 时长(ms) | 信息提示,默认 3s |
| $toast.success(content, timeout?) | 同上 | 成功提示 |
| $toast.warning(content, timeout?) | 同上 | 警告提示 |
| $toast.error(content, timeout?) | 同上 | 错误提示 |
$notice
通知栏消息,含标题和内容。
import { $notice } from 'easyui';
$notice.info('这是一条通知', '通知标题', 5000);
$notice.success('操作成功', '提示');
$notice.warning('数据即将过期', '警告');
$notice.error('服务器错误', '错误');| 方法 | 参数 | 说明 |
|------|------|------|
| $notice.info(content, title?, timeout?) | 内容, 标题, 时长 | 信息通知 |
| $notice.success(content, title?, timeout?) | 同上 | 成功通知 |
| $notice.warning(content, title?, timeout?) | 同上 | 警告通知 |
| $notice.error(content, title?, timeout?) | 同上 | 错误通知 |
| $notice.validate(errors[], title?, timeout?) | 同上 | 验证错误通知 |
$alert
模态对话框提示(Alert)。
import { $alert } from 'easyui';
$alert.info('提示', '这是一条消息');
$alert.warning('警告', '请确认操作');
$alert.error('错误', '操作失败');| 方法 | 参数 |
|------|------|
| $alert.info(title, content) | 标题, 内容 |
| $alert.warning(title, content) | 同上 |
| $alert.error(title, content) | 同上 |
$confirm / $prompt
交互式确认框和输入框。
import { $confirm, $prompt } from 'easyui';
// 确认框
$confirm('确认删除?', '此操作不可恢复', () => {
console.log('确认');
}, () => {
console.log('取消');
});
// 输入框
$prompt('请输入名称', '', (value) => {
console.log('输入值:', value);
}, () => {
console.log('取消');
});| 函数 | 参数 | 说明 |
|------|------|------|
| $confirm(title, content, okFn, cancelFn?) | 标题, 内容, 确认回调, 取消回调 | 确认对话框 |
| $prompt(title, content, okFn, cancelFn?) | 标题, 内容, 确认回调(含输入值), 取消回调 | 输入对话框 |
工具函数
setSideMenuState
设置侧边栏菜单选中/展开状态。
import { setSideMenuState } from 'easyui';
const menus = setSideMenuState(menuData, ['menu-1', 'menu-1-1']);| 参数 | 类型 | 说明 |
|------|------|------|
| data | Array | 菜单数据 |
| actives | Array | 选中的菜单 ID 列表 |
| 返回值 | Array | 设置好 state/selected 的菜单数据 |
toComboBox
数组转为 ComboBox 需要的 {value, text} 格式。
import { toComboBox } from 'easyui';
const options = toComboBox(users, 'id', 'name');
// [{ value: 1, text: '张三' }, ...]| 参数 | 类型 | 说明 |
|------|------|------|
| origins | Array | 原始数组 |
| key | string | value 字段名 |
| text | string | text 字段名 |
Composable / Hooks
useLocale
国际化语言切换(依赖状态管理 store)。
import { useLocale } from 'easyui';
const { locale, localeOptions, changeLocale } = useLocale(true);
changeLocale('en'); // 切换语言并刷新页面| 返回值 | 类型 | 说明 |
|--------|------|------|
| locale | string | 当前语言 |
| localeOptions | Array | 可用语言列表 |
| changeLocale | (key: string) => void | 切换语言 |
useTheme
主题切换(依赖状态管理 store)。
import { useTheme } from 'easyui';
const { changeTheme, themeOptions, loadHtmlTheme } = useTheme('/themes/');
changeTheme('cartoon'); // 切换主题并刷新
loadHtmlTheme(); // 初始化加载主题| 返回值 | 类型 | 说明 |
|--------|------|------|
| changeTheme | (theme: string) => void | 切换主题 |
| themeOptions | Array | 可选主题列表 |
| loadHtmlTheme | () => void | 动态加载主题 CSS |
useRefDialog
对话框/弹窗 ref 管理 Hook。
import { useRefDialog } from 'easyui';
const dialog = useRefDialog({ title: '默认标题' });
dialog.open({ title: '新标题' }); // 打开并传参
dialog.close(); // 关闭
dialog.value.current; // rc-easyui Dialog ref直接使用的 Messager Ref
import { Alert, Confirm, Prompt } from 'easyui';
// 需要先在 JSX 中挂载 Messager 组件
<Messager ref={messagerAlertRef} />
<Messager ref={messagerConfirmRef} />
<Messager ref={messagerPromptRef} />
// 然后调用
Alert('提示', '消息内容', 'warn');
Confirm('确认', '是否继续?', 'warn', '自定义内容', () => {}, () => {});
Prompt('输入', '请输入', 'warn', '', (val) => {});目录结构
easyui/
├── src/
│ ├── index.ts ← 入口,统一导出
│ ├── components/
│ │ ├── layouts/ ← AdminLayout
│ │ ├── panel/ ← DrawerPanel, DefaultPanel, Card, Breadcrumb, TabsPanel
│ │ ├── form/ ← CheckboxGroupBox, RadioGroupBox
│ │ ├── grid/ ← withCheckGrid, withRadioGrid
│ │ ├── message/ ← toast, notification, alert, interactive
│ │ └── access.tsx ← 权限组件
│ ├── composable/ ← useLocale, useTheme, useRefDialog
│ ├── util/ ← easyui 工具, message ref
│ └── assets/
│ ├── index.scss ← 基础样式入口
│ └── react-drawer.scss ← 抽屉基础结构样式
├── public/themes/ ← 主题皮肤
├── examples/ ← 组件测试示例
└── package.json开发命令
# 开发模式(带示例页)
npm run dev:examples
# 构建
npm run build:examples
# 运行测试
npm test浏览器支持
- Chrome / Edge / Safari / Firefox 最新两个大版本
- React 18+
- 推荐分辨率 >= 1280px
