基础表格 BaseList
BaseList
是一个功能强大、可复用的基础列表组件,集成了查询表单、功能操作区、分页、多选操作等常见数据展示功能。
✅ 表格 Demo 示例 (完整的增删改查)
- 示例
- 源码

import { Delete, Smartphone } from "lucide-react";
import React, { useRef, useState } from "react";
import { BaseList } from '@npmqg/react-ui-baselist';
import { Button, Input, Modal, Space } from '@npmqg/react-ui-core';
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '@npmqg/react-ui-form';
import { Intl } from '@npmqg/utils-locale-toggle';
import { message } from '@npmqg/utils-message';
import UserManageSaveOrUpdateWrap from '../SaveOrUpdate/wrap';
import UserManageViewModal from '../View';
function UserManage() {
//执行子组件 (列表组件) 方法
const ref = useRef();
const [localEditData, setLocalData] = useState({});
const [localViewData, setLocalViewData] = useState({});
const [saveVisible, setSaveVisible] = useState(false);
const [viewVisible, setViewVisible] = useState(false);
//搜索表单
const searchData = useRef([
{
key: "mobile",
value: (
<FormField
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v("手机号")}</FormLabel>
<FormControl>
<Input
maxLength={20}
placeholder={Intl.v("请输入手机号")}
prefix={<Smartphone size={20} />}
{...field}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
),
defaultValue: "",
},
]);
//表头
const columns = useRef([
{
header: "序号",
accessorKey: "index",
size: 80,
sticky: "left",
cell: (info) => info.getValue(),
},
{
header: "手机号",
accessorKey: "mobile",
size: 200,
sticky: "left",
cell: (info) => info.getValue(),
},
{
header: "邀请码",
accessorKey: "invite_code",
size: 200,
wrap: true,
cell: (info) => info.getValue(),
},
{
header: "操作",
accessorKey: "actions",
size: 200,
sticky: "right",
cell: ({ row }) => {
const record = row.original;
return (
<Space size={12}>
<Button
onClick={() => onEdit(record)}
size="zero"
textColor="primary"
variant="link"
>
{Intl.v("编辑")}
</Button>
<Button
onClick={() => onDelete(record)}
size="zero"
textColor="danger"
variant="link"
>
{Intl.v("删除")}
</Button>
<Button
onClick={() => onView(record)}
size="zero"
textColor="info"
variant="link"
>
{Intl.v("查看")}
</Button>
</Space>
);
},
enableSorting: false,
enableColumnFilter: false,
},
]);
//列头操作按钮
const optionButtonGroup = useRef([
<Button key="save" onClick={onSave}>
{Intl.v("新增")}
</Button>,
<Button key="del" onClick={onBatchDelete}>
{Intl.v("批量删除")}
</Button>,
]);
//查询列表数据
async function requestListAllData(params = {}, callback) {
//message.success('触发查询' + JSON.stringify(params));
// const res = await requestUserList(params);
//
// if (res?.code !== 200) {
// res?.msg && message.warning(res?.msg);
//
// callback?.(false);
//
// return;
// }
//将数据格式整理成 如下然后传入查询表格组件
const resData = {
// dataSource: res.data?.list || [],
dataSource: [
{
uuid: "f0b-5692b5c28bcd",
status: 1,
email: "Si63.com",
username: "",
mobile: "152769",
invite_code: "AD6KHD",
password: "",
raw_password: "123456",
create_time: "",
update_time: "",
},
{
uuid: "065bc3e50feec",
status: 1,
email: "252@qq.com",
username: "QG",
mobile: "154066",
invite_code: "JF9XYX",
password: "",
raw_password: "123456",
create_time: "",
update_time: "",
},
],
total: 2,
};
callback?.(resData);
}
//删除
function onDelete(record) {
Modal.confirm({
title: `确认删除【${record?.mobile}】?`,
icon: <Delete />,
wrapClassName: "centered-modal",
onOk: async () => {
// const res = await requestDelUserById({ uuid: record.uuid });
//
// if (res?.code !== 200) {
// res?.msg && message.warning(res?.msg);
//
// return;
// }
//
// //清理多选项
// ref.current?.onChangeRowSelection(record.uuid);
//
// message.success(res?.msg + record?.mobile);
message.success("删除成功");
//刷新列表
ref.current?.onSearch?.();
},
});
}
//批量删除
function onBatchDelete() {
const mobile = ref.current?.state.selectedRows
.map((item) => item.mobile)
.join(",");
const uuids = ref.current?.state.selectedRowKeys.join(",");
if (!mobile) {
message.warning("请先选择用户");
return;
}
Modal.confirm({
title: `确认删除【${mobile}】?`,
icon: <Delete />,
wrapClassName: "centered-modal",
onOk: async () => {
// const res = await requestDelUserById({
// uuid: uuids,
// });
//
// if (res?.code !== 200) {
// res?.msg && message.warning(res?.msg);
//
// return;
// }
//
// //清理多选项
// ref.current?.onChangeRowSelection(uuids);
//
// message.success(res?.msg + mobile);
message.success("删除成功");
//刷新列表
ref.current?.onSearch?.();
},
});
}
//新增
function onSave() {
setLocalData({
data: null,
title: "新增用户",
});
onUserManageEditOpen();
}
//编辑
function onEdit(data) {
setLocalData({
data,
title: "编辑用户",
});
onUserManageEditOpen();
}
//查看
function onView(data) {
setLocalViewData({
data,
title: "查看用户信息",
});
onUserManageViewOpen();
}
//关闭编辑弹窗
function onUserManageEditCancel(isRefresh) {
setSaveVisible(false);
isRefresh && ref.current?.onSearch?.();
}
//打开编辑 弹窗
function onUserManageEditOpen() {
setSaveVisible(true);
}
//关闭查看弹窗
function onUserManageViewCancel() {
setViewVisible(false);
}
//打开查看弹窗
function onUserManageViewOpen() {
setViewVisible(true);
}
return (
<div>
<BaseList
columns={columns.current} //表头
isShowRowTitleName="mobile" //多选展示的字段值
locales="zh_CN"
openRowSelection
optionButtonGroup={optionButtonGroup.current} //表头上方操作按钮
ref={ref}
searchParamList={searchData.current}
serviceFunc={requestListAllData} // 请求数据方法
/>
{/*新建编辑弹出层*/}
<UserManageSaveOrUpdateWrap
{...localEditData}
onCancel={onUserManageEditCancel}
open={saveVisible}
/>
{/*查看弹出层*/}
<UserManageViewModal
{...localViewData}
onCancel={onUserManageViewCancel}
open={viewVisible}
/>
</div>
);
}
export default UserManage;
✅ 对话框:新增/修改 Demo 示例
📚数据处理 wrap.jsx
import React, { useEffect, useRef } from "react";
import message from "@/utils/message";
import { requestSaveUser, requestUpdateUser } from "@/services/user";
import Index from "./index";
function BannerListWrap({ data, onCancel, open, title }) {
const ref = useRef();
async function onSubmit(values) {
if (values?.uuid) {
//编辑 调用接口的方法需要自定义
const res = await requestUpdateUser(values);
if (res?.code === 200) {
message.success(res?.msg);
//关闭Modal
onCancel();
} else {
message.error(res?.msg);
}
} else {
//新增 调用接口的方法需要自定义
values?.uuid && delete values["uuid"];
const res = await requestSaveUser(values);
if (res?.code === 200) {
message.success(res?.msg);
//关闭Modal
onCancel();
} else {
message.error(res?.msg);
}
}
}
useEffect(() => {
if (data) {
ref.current?.form?.reset(data);
} else {
ref.current?.form?.reset(ref.current?.formDefaultValue);
}
}, [data]);
return (
<Index
onCancel={onCancel}
onSubmit={onSubmit}
open={open}
ref={ref}
title={title}
/>
);
}
export default BannerListWrap;
📚 数据展示 index.jsx
import React, { forwardRef, useImperativeHandle, useRef } from 'react';
import { useForm } from 'react-hook-form';
import { FormComponents } from '@/components/system/FormComponents';
import { Intl } from '@/components/system/Intl';
import { Modal } from '@/components/system/Modal';
import { Button } from '@/components/ui/Button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/Form';
import { Input } from '@/components/ui/Input';
function UserManageModal({ onSubmit = () => null, title = '', open = false, onCancel = () => void 0 }, ref) {
const formDefaultValue = useRef({
uuid: '',
status: '1',
mobile: '',
email: '',
username: '',
raw_password: '',
password: '',
invite_code: '',
});
const form = useForm({
defaultValues: formDefaultValue.current,
mode: 'onChange', // 可以是 'onChange'、'onSubmit' 等
});
useImperativeHandle(ref, () => ({
form,
formDefaultValue,
}));
return (
<Modal onCancel={onCancel} open={open} title={title} width={300}>
{() => (
<Form {...form}>
<form className="space-y-6 flex flex-col rounded-md p-4" onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="uuid"
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormControl className="hidden">
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="status"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('状态')}</FormLabel>
<FormControl>
<FormComponents init="SystemUserStatus" type="select" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="mobile"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('手机号')}</FormLabel>
<FormControl>
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
rules={{
required: Intl.v('请输入手机号'),
}}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('邮箱')}</FormLabel>
<FormControl>
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
rules={{
required: Intl.v('请输入邮箱'),
}}
/>
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('昵称')}</FormLabel>
<FormControl>
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
rules={{
required: Intl.v('请输入昵称'),
}}
/>
<FormField
control={form.control}
name="raw_password"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('密码')}</FormLabel>
<FormControl>
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
rules={{
required: Intl.v('请输入密码'),
}}
/>
<FormField
control={form.control}
name="invite_code"
render={({ field }) => (
<FormItem>
<FormLabel>{Intl.v('邀请码')}</FormLabel>
<FormControl>
<Input maxLength={20} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
rules={{
required: Intl.v('请输入邀请码'),
}}
/>
<Button className="w-full">{Intl.v('保存')}</Button>
</form>
</Form>
)}
</Modal>
);
}
export default forwardRef(UserManageModal);
✅ 对话框:查看 Demo 示例
import React from 'react';
import { Intl } from '@/components/system/Intl';
import { Modal } from '@/components/system/Modal';
import styles from './index.scss';
function UserManageViewModal({ data = {}, title = '', open = false, onCancel = () => void 0 }) {
return (
<Modal onCancel={onCancel} open={open} title={title}>
{() => (
<div className={styles.UserManageViewModal}>
<div>
<label>{Intl.v('用户名')}</label>
<div>{data.username}</div>
</div>
</div>
)}
</Modal>
);
}
export default UserManageViewModal;
📦 Props 参数
参 数名 | 类型 | 默认值 | 说明 |
---|---|---|---|
serviceFunc | (params, callback) => void | () => {} | 数据请求函数,必须调用 callback({ dataSource, total }) 返回数据 |
functionControlTableTitle | string | '查询表格' | 功能区域标题 |
columns | any[] | [] | 表格列配置,传入给 ListBody |
optionButtonGroup | ReactNode[] | [] | 功能操作按钮组 |
searchParamList | ISearchParam[] | [] | 查询表单配置项 |
functionControlHide | boolean | false | 是否隐藏功能操作栏 |
topPagination | boolean | false | 是否显示顶部分页 |
bottomPagination | boolean | true | 是否显示底部分页 |
isShowRowTitleName | string | '' | 多选项中用于显示的字段名(如 name ) |
noSearch | boolean | false | 是否在初始化时禁止自动触发查询 |
className | string | - | 自定义样式类名 |
openRowSelection | boolean | false | 是否启用多选行 |
🔧 方法(通过 ref 暴露)
使用 ref
可以访问以下方法和状态:
const ref = useRef<any>();
<BaseList ref={ref} {...props} />;
// 访问方法
ref.current?.onSearch(); // 重新触发搜索
ref.current?.onChangeRowSelection('uuid1,uuid2'); // 删除多选项
console.log(ref.current?.state); // 获取当前状态
方法名 | 说明 |
---|---|
onSearch(condition?) | 手动触发查询(传参可覆盖) |
onChangeRowSelection(ids) | 删除指定 uuid 的多选项 |
state | 当前组件内部状态 |
🧮 状态(state 类型)
interface IStateProps {
isHideFormItem: boolean;
tableDensity: string;
loading: boolean;
dataSource: any[];
selectedRows: any[];
selectedRowKeys: any[];
isShowRowTitleName: string;
Condition: Record<string, any>;
current: number;
pageSize: number;
total: number;
}