npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

temp-antd

v0.0.4

Published

本文档详细介绍了项目中的两个核心组件:`DynamicForm`(动态表单组件)和 `ListTable`(列表表格组件)的使用方法、属性配置和示例代码。

Readme

DynamicForm 和 ListTable 组件使用文档

本文档详细介绍了项目中的两个核心组件:DynamicForm(动态表单组件)和 ListTable(列表表格组件)的使用方法、属性配置和示例代码。

一、DynamicForm 组件

1. 组件介绍

DynamicForm 是一个灵活的动态表单组件,支持多种表单项类型配置、响应式布局和折叠/展开功能。它基于 Ant Design 的 Form 组件进行封装,极大简化了复杂表单的构建过程。

2. 组件属性

| 属性名 | 类型 | 默认值 | 说明 | |-------|------|-------|------| | items | FormItem[] | 必填 | 表单项配置数组 | | onSubmit | (values: Record<string, unknown>) => void | 必填 | 表单提交回调函数 | | layout | 'inline' \| 'horizontal' \| 'vertical' | 'horizontal' | 表单项标签对齐方式 | | onReset | () => void | 可选 | 表单重置回调函数 | | form | FormInstance | 可选 | 外部传入的 form 实例 | | collapsed | boolean | false | 初始折叠状态 | | submitText | string | '提交' | 提交按钮文本 | | resetText | string | '重置' | 重置按钮文本 | | defaultShowCount | number | 0 | 默认显示的表单项数量 | | labelCol | Record<string, unknown> | { span: 6 } | 标签列宽度配置 | | wrapperCol | Record<string, unknown> | { span: 16 } | 表单项列宽度配置 | | itemsPerRow | number | 3 | 每行显示的表单项数量 | | onCollapseChange | (collapsed: boolean) => void | 可选 | 折叠状态变化回调 |

3. FormItem 接口定义

interface FormItem {
  label: string; // 表单项标签
  name: string; // 表单项字段名
  type: 
    | "text" 
    | "select" 
    | "date" 
    | "number" 
    | "checkbox" 
    | "radio" 
    | "cascader" 
    | "custom" 
    | "remoteSelect"; // 表单项类型
  props?: Record<string, unknown>; // 传递给具体组件的属性
  options?: { label: string; value: string | number }[]; // 仅当 type 为 select, radio, checkbox 时使用
  rules?: Record<string, unknown>[]; // 校验规则
  customRender?: React.ReactNode; // 当 type 为 custom 时使用
}

4. 使用示例

基础用法

import React from 'react';
import { Button } from 'antd';
import DynamicForm from './components/DynamicForm';

const MyFormPage: React.FC = () => {
  // 表单项配置
  const formItems = [
    {
      label: '姓名',
      name: 'name',
      type: 'text',
      rules: [{ required: true, message: '请输入姓名' }]
    },
    {
      label: '年龄',
      name: 'age',
      type: 'number',
      props: { min: 18, max: 100 }
    },
    {
      label: '性别',
      name: 'gender',
      type: 'radio',
      options: [
        { label: '男', value: 'male' },
        { label: '女', value: 'female' }
      ]
    },
    {
      label: '兴趣爱好',
      name: 'hobbies',
      type: 'checkbox',
      props: { mode: 'multiple' },
      options: [
        { label: '阅读', value: 'reading' },
        { label: '运动', value: 'sports' },
        { label: '音乐', value: 'music' }
      ]
    },
    {
      label: '出生日期',
      name: 'birthday',
      type: 'date',
      props: { format: 'YYYY-MM-DD' }
    },
    {
      label: '所在城市',
      name: 'city',
      type: 'cascader',
      options: [
        {
          label: '北京',
          value: 'beijing',
          children: [{ label: '朝阳区', value: 'chaoyang' }]
        },
        {
          label: '上海',
          value: 'shanghai',
          children: [{ label: '浦东新区', value: 'pudong' }]
        }
      ]
    }
  ];

  // 处理表单提交
  const handleSubmit = (values: Record<string, unknown>) => {
    console.log('表单提交数据:', values);
    // 这里可以处理表单提交逻辑,如API请求等
  };

  return (
    <div>
      <h2>用户信息表单</h2>
      <DynamicForm 
        items={formItems} 
        onSubmit={handleSubmit} 
        defaultShowCount={3} // 默认显示3个表单项,其余可折叠
        itemsPerRow={2} // 每行显示2个表单项
      />
    </div>
  );
};

export default MyFormPage;

使用自定义组件

import React from 'react';
import { Input, Rate, Slider } from 'antd';
import DynamicForm from './components/DynamicForm';

const CustomFormPage: React.FC = () => {
  const formItems = [
    // 其他表单项...
    {
      label: '评分',
      name: 'rating',
      type: 'custom',
      customRender: <Rate />,
      rules: [{ required: true, message: '请评分' }]
    },
    {
      label: '自定义输入',
      name: 'customInput',
      type: 'custom',
      customRender: (
        <>
          <Input placeholder="前缀" style={{ width: '40%', marginRight: 10 }} />
          <Input placeholder="后缀" style={{ width: '40%' }} />
        </>
      )
    }
  ];

  const handleSubmit = (values: Record<string, unknown>) => {
    console.log('提交数据:', values);
  };

  return (
    <DynamicForm 
      items={formItems} 
      onSubmit={handleSubmit} 
    />
  );
};

二、ListTable 组件

1. 组件介绍

ListTable 是一个功能强大的列表表格组件,整合了数据展示、分页、搜索和工具栏等功能。它基于 Ant Design 的 Table 组件进行封装,可以快速构建完整的数据列表页面。

2. 组件属性

| 属性名 | 类型 | 默认值 | 说明 | |-------|------|-------|------| | columns | ListTableColumn[] | 必填 | 表格列配置数组 | | request | (params: any) => Promise<{ data: T[]; success: boolean; total: number }> | 必填(除非提供dataSource) | 数据请求函数 | | dataSource | T[] | 可选 | 本地数据源,如果提供则不执行request | | toolBarRender | () => ReactNode[] | 可选 | 自定义工具栏按钮渲染函数 | | tableTitle | ReactNode | 可选 | 表格标题 | | pagination | { pageSize?: number; current?: number; total?: number; showSizeChanger?: boolean; showQuickJumper?: boolean; onChange?: (page: number, pageSize: number) => void } \| false | 可选 | 分页配置,传false则不显示分页 | | ...tableProps | TableProps<T> | 可选 | 其他Ant Design Table组件属性 |

3. ListTableColumn 接口定义

interface ListTableColumn<T = any> extends Omit<ColumnType<T>, 'dataIndex'> {
  dataIndex: string; // 数据字段名
  hideInSearch?: boolean; // 是否在搜索表单中隐藏
  hideInTable?: boolean; // 是否在表格中隐藏
  valueEnum?: Pick<FormItem, 'options'> | Record<string, { label: string; value?: string }>; // 枚举值配置
  formItemProps?: Omit<FormItem, 'label' | 'name' | 'options'>; // 搜索表单项属性
}

4. 使用示例

基础用法(使用远程数据源)

import React from 'react';
import { Button } from 'antd';
import ListTable, { ListTableColumn } from './components/ListTable';

interface User {
  id: string;
  name: string;
  age: number;
  gender: 'male' | 'female';
  status: 'active' | 'inactive' | 'pending';
  createTime: string;
}

const UserListPage: React.FC = () => {
  // 列配置
  const columns: ListTableColumn<User>[] = [
    {
      title: '用户ID',
      dataIndex: 'id',
      key: 'id',
      width: 80
    },
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name'
    },
    {
      title: '年龄',
      dataIndex: 'age',
      key: 'age',
      width: 80
    },
    {
      title: '性别',
      dataIndex: 'gender',
      key: 'gender',
      width: 80,
      valueEnum: {
        options: [
          { label: '男', value: 'male' },
          { label: '女', value: 'female' }
        ]
      }
    },
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      width: 100,
      valueEnum: {
        active: { label: '活跃' },
        inactive: { label: '禁用' },
        pending: { label: '待审核' }
      }
    },
    {
      title: '创建时间',
      dataIndex: 'createTime',
      key: 'createTime'
    },
    {
      title: '操作',
      key: 'action',
      width: 150,
      render: (_, record) => (
        <>
          <Button type="link" style={{color:'#2BA07F',fontSize:'14px'}} onClick={() => handleEdit(record)}>
            编辑
          </Button>
          <Button type="link" danger onClick={() => handleDelete(record.id)}>
            删除
          </Button>
        </>
      )
    }
  ];

  // 数据请求函数
  const request = async (params: any) => {
    // 模拟API请求
    console.log('请求参数:', params);
    // 实际项目中这里应该调用真实的API
    // const response = await api.getUsers(params);
    // return response;
    
    // 模拟数据
    return {
      success: true,
      total: 100,
      data: Array(10).fill(0).map((_, index) => ({
        id: `user_${params.page || 1}_${index + 1}`,
        name: `用户${(params.page || 1) * 10 + index}`,
        age: 18 + Math.floor(Math.random() * 30),
        gender: Math.random() > 0.5 ? 'male' : 'female',
        status: ['active', 'inactive', 'pending'][Math.floor(Math.random() * 3)],
        createTime: new Date(Date.now() - Math.random() * 10000000000).toISOString()
      }))
    };
  };

  // 自定义工具栏
  const toolBarRender = () => [
    <Button key="add" type="primary" style={{backgroundColor: '#2BA07F', borderColor: '#2BA07F'}}>
      添加用户
    </Button>
  ];

  // 处理编辑
  const handleEdit = (record: User) => {
    console.log('编辑用户:', record);
    // 实现编辑逻辑
  };

  // 处理删除
  const handleDelete = (id: string) => {
    console.log('删除用户:', id);
    // 实现删除逻辑
  };

  return (
    <div>
      <h2>用户管理列表</h2>
      <ListTable
        columns={columns}
        request={request}
        tableTitle="用户列表"
        toolBarRender={toolBarRender}
        pagination={{
          pageSize: 10,
          showSizeChanger: true,
          showQuickJumper: true
        }}
      />
    </div>
  );
};

export default UserListPage;

使用本地数据源

import React from 'react';
import ListTable from './components/ListTable';

const LocalDataPage: React.FC = () => {
  // 本地数据源
  const localData = [
    { id: '1', name: '张三', age: 25, department: '开发部' },
    { id: '2', name: '李四', age: 30, department: '市场部' },
    { id: '3', name: '王五', age: 35, department: '设计部' }
  ];

  // 列配置
  const columns = [
    { title: 'ID', dataIndex: 'id', key: 'id' },
    { title: '姓名', dataIndex: 'name', key: 'name' },
    { title: '年龄', dataIndex: 'age', key: 'age' },
    { title: '部门', dataIndex: 'department', key: 'department' }
  ];

  // 空的请求函数(因为使用本地数据源)
  const emptyRequest = async () => ({
    success: true,
    data: [],
    total: 0
  });

  return (
    <ListTable
      columns={columns}
      request={emptyRequest} 
      dataSource={localData} // 使用本地数据源
      pagination={{
        pageSize: 10,
        showSizeChanger: false
      }}
    />
  );
};

三、组件组合使用

以下示例展示如何结合 DynamicFormListTable 组件,构建一个完整的数据管理页面:

import React, { useState } from 'react';
import { Button, Modal, message } from 'antd';
import DynamicForm from './components/DynamicForm';
import ListTable from './components/ListTable';

interface Product {
  id: string;
  name: string;
  price: number;
  category: string;
  stock: number;
}

const ProductManagementPage: React.FC = () => {
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [editingProduct, setEditingProduct] = useState<Product | null>(null);

  // 产品表单配置
  const productFormItems = [
    {
      label: '产品名称',
      name: 'name',
      type: 'text',
      rules: [{ required: true, message: '请输入产品名称' }]
    },
    {
      label: '产品价格',
      name: 'price',
      type: 'number',
      props: { min: 0, step: 0.01, precision: 2 },
      rules: [{ required: true, message: '请输入产品价格' }]
    },
    {
      label: '产品分类',
      name: 'category',
      type: 'select',
      options: [
        { label: '电子产品', value: 'electronics' },
        { label: '服装鞋帽', value: 'clothing' },
        { label: '食品饮料', value: 'food' }
      ],
      rules: [{ required: true, message: '请选择产品分类' }]
    },
    {
      label: '库存数量',
      name: 'stock',
      type: 'number',
      props: { min: 0, step: 1 },
      rules: [{ required: true, message: '请输入库存数量' }]
    }
  ];

  // 表格列配置
  const columns = [
    { title: '产品ID', dataIndex: 'id', key: 'id' },
    { title: '产品名称', dataIndex: 'name', key: 'name' },
    { title: '产品价格', dataIndex: 'price', key: 'price', render: (price) => `¥${price}` },
    { title: '产品分类', dataIndex: 'category', key: 'category' },
    { title: '库存数量', dataIndex: 'stock', key: 'stock' },
    {
      title: '操作',
      key: 'action',
      render: (_, record) => (
        <>
          <Button type="link" style={{color:'#2BA07F',fontSize:'14px'}} onClick={() => handleEdit(record)}>
            编辑
          </Button>
          <Button type="link" danger onClick={() => handleDelete(record.id)}>
            删除
          </Button>
        </>
      )
    }
  ];

  // 数据请求函数
  const request = async (params: any) => {
    // 实际项目中这里应该调用真实的API
    console.log('请求参数:', params);
    // 模拟数据返回
    return {
      success: true,
      total: 50,
      data: Array(10).fill(0).map((_, index) => ({
        id: `prod_${params.page || 1}_${index + 1}`,
        name: `产品${(params.page || 1) * 10 + index}`,
        price: 10 + Math.random() * 990,
        category: ['electronics', 'clothing', 'food'][Math.floor(Math.random() * 3)],
        stock: Math.floor(Math.random() * 1000)
      }))
    };
  };

  // 打开添加/编辑模态框
  const showModal = (product: Product | null = null) => {
    setEditingProduct(product);
    setIsModalVisible(true);
  };

  // 处理编辑
  const handleEdit = (product: Product) => {
    showModal(product);
  };

  // 处理删除
  const handleDelete = (id: string) => {
    console.log('删除产品:', id);
    // 实际项目中这里应该调用删除API
    message.success('产品删除成功');
  };

  // 处理表单提交
  const handleSubmit = (values: Record<string, unknown>) => {
    console.log('提交产品数据:', values);
    // 实际项目中这里应该调用保存API
    setIsModalVisible(false);
    message.success(editingProduct ? '产品更新成功' : '产品添加成功');
    setEditingProduct(null);
  };

  // 自定义工具栏
  const toolBarRender = () => [
    <Button key="add" type="primary" style={{backgroundColor: '#2BA07F', borderColor: '#2BA07F'}} onClick={() => showModal()}>
      添加产品
    </Button>
  ];

  return (
    <div>
      <h2>产品管理系统</h2>
      <ListTable
        columns={columns}
        request={request}
        toolBarRender={toolBarRender}
        pagination={{
          pageSize: 10,
          showSizeChanger: true,
          showQuickJumper: true
        }}
      />

      {/* 添加/编辑产品模态框 */}
      <Modal
        title={editingProduct ? '编辑产品' : '添加产品'}
        open={isModalVisible}
        onCancel={() => {
          setIsModalVisible(false);
          setEditingProduct(null);
        }}
        footer={null}
        width={600}
      >
        <DynamicForm
          items={productFormItems}
          onSubmit={handleSubmit}
          itemsPerRow={1}
        />
      </Modal>
    </div>
  );
};

export default ProductManagementPage;

四、主题颜色配置

项目中主题色已配置为 #2BA07F(一种绿色系颜色),在按钮、链接等交互元素中统一使用了这个颜色。如果需要自定义组件的颜色,可以通过 style 属性覆盖默认样式:

<Button 
  type="link" 
  style={{color:'#2BA07F',fontSize:'14px'}} 
  onClick={handleEdit}
>
  编辑
</Button>

<Button 
  type="primary" 
  style={{backgroundColor: '#2BA07F', borderColor: '#2BA07F'}} 
  onClick={handleAdd}
>
  添加
</Button>

五、注意事项

  1. 版本兼容性:组件基于 Ant Design v5 开发,使用时请确保项目中 Ant Design 版本与之兼容。

  2. 数据格式:使用 ListTable 组件时,数据请求函数 request 需要返回包含 datasuccesstotal 三个字段的对象。

  3. 性能优化:对于大量数据,建议使用 request 进行分页加载,而不是一次性加载所有数据。

  4. 表单验证DynamicForm 组件支持 Ant Design 的表单验证规则,可通过 rules 属性配置。