GeneralInfo -- 一般详情

Ant Design 的封装组件,这个组件不仅继承了 Ant Design 的美观和功能性,还增加了额外的定制性和易用性,使其成为展示详情信息或其他类似数据的完美选择。

GeneralInfo 的优势
高度定制性

GeneralInfo组件提供了丰富的 API,允许开发者根据具体需求定制每一个细节。通过 Property 接口,你可以轻松定义每个属性的标签、获取值的函数、是否显示的条件,以及更多的布局属性。

灵活的数据展示

利用 getValue 函数,开发者可以灵活地定义如何展示数据。这不仅支持直接的数据展示,还可以进行复杂的数据处理,如格式化日期或货币。

易于集成和使用

GeneralInfo 组件设计为易于集成和使用。只需几行代码,你就可以在你的 React 项目中使用它,无论是展示合同信息还是其他任何结构化数据。

相关依赖

React:作为构建用户界面的 JavaScript 库。

Ant Design:一个流行的 React UI 库,提供了丰富的组件和美观的主题。

话不多说,上干货!!!

使用效果:

关于源码:ps 这里使用的是4x版本的react

import React from 'react'
import { Descriptions } from 'antd'
import type { DescriptionsProps } from 'antd/lib/descriptions'
import type { DescriptionsItemProps } from 'antd/lib/descriptions/Item'
import './style.scoped.css'

const { Item } = Descriptions

/**
 * @interface Property 属性结构定义
 * @property {string} label - 标签
 * @property {(item: any) => string | number | React.ReactNode} getValue - 获取值的函数
 * @property {(item: any) => boolean} [shouldDisplay] - 是否显示的函数,默认为 true
 */
interface Property {
  unit?: string
  label: string
  getValue: (item: any) => string | number | React.ReactNode
  shouldDisplay?: (item: any) => boolean
  itemProps?: DescriptionsItemProps
}

/**
 * @interface GeneralInfoProps 组件属性接口
 * @property {any} dataSource - 数据源对象
 * @property {Property[]} properties - 配置项-属性结构数组
 * @property {string | React.ReactNode | undefined} [title] - 标题,默认为空字符串
 * @property {string | React.ReactNode | undefined} [titleComponent] - 标题组件,默认为空
 */
interface GeneralInfoProps extends Omit<DescriptionsProps, 'title'> {
  dataSource: any
  styleCSS?: React.CSSProperties
  properties: Property[]
  title?: string | React.ReactNode
  titleComponent?: React.ReactNode
}

/**
 * @function GeneralInfo 封装的详情组件
 * @param {GeneralInfoProps} props - 组件属性
 * @description 封装的详情组件
 * @example <GeneralInfo dataSource={dataSource} properties={properties} />
 * @returns React.ReactNode
 */
function GeneralInfo({
  dataSource,
  properties,
  title: titleProp,
  titleComponent: titleComponentProp,
  styleCSS,
  children,
  ...props
}: GeneralInfoProps) {
  // 确保至少提供了 title 或 titleComponent
  const effectiveTitle = titleComponentProp ?? (
    <div className="title-adorn">{titleProp ? titleProp : '默认标题'}</div>
  )

  return (
    <Descriptions
      style={styleCSS || { marginLeft: 20 }}
      {...props}
      title={effectiveTitle}>
      {properties.map((property) => {
        const item = dataSource // 获取数据源对象
        if (!property.shouldDisplay || property.shouldDisplay(item)) {
          return (
            <Item
              {...property?.itemProps}
              label={property.label}
              key={property.label}>
              {property.getValue(item) === 0
                ? 0
                : property.getValue(item) || '-'}
              {property.unit && <span>&nbsp;{property.unit}</span>}
            </Item>
          )
        }
        return null
      })}
      {children}
    </Descriptions>
  )
}

export default GeneralInfo

关于文档:
 

import React from 'react'
import type { Meta, StoryObj } from '@storybook/react'
import GeneralInfo from '../../components/GeneralInfo'
import type { DescriptionsItemProps } from 'antd/lib/descriptions/Item'

const meta = {
  title: '常用详情布局/GeneralInfo',
  component: GeneralInfo,
  tags: ['autodocs'],
  argTypes: {
    title: {
      description: '标题',
      table: {
        type: { summary: 'string | ReactNode' }
      }
    },
    titleComponent: {
      description: '自定义标题组件',
      table: {
        type: { summary: 'string | ReactNode' }
      }
    },
    dataSource: {
      description: '数据源',
      table: {
        type: { summary: 'Object' }
      }
    },
    properties: {
      description: '配置项',
      table: {
        type: {
          summary:
            '{ label:string, getValue:(item)=>string | number | React.ReactNode, unit?:string, shouldDisplay?:(item)=>boolean, itemProps?:DescriptionsItemProps }[]'
        }
      }
    },
    styleCSS: {
      description: '内联样式',
      table: {
        type: { summary: 'CSSProperties' }
      }
    },
    children: {
      description: '自定义内容',
      table: {
        type: { summary: 'ReactNode' }
      }
    }
  }
} satisfies Meta<typeof GeneralInfo>

export default meta
type Story = StoryObj<typeof meta>

export const Example: Story = {
  args: {
    title: '常用信息',
    dataSource: {
      name: '测试数据',
      code: '1212129103243',
      city: '浙江省杭州市',
      address: '浙江省杭州市西湖区浙大科技园',
      type: '2',
      status: '待处理',
      startDate: '2024-10-21 10:00:00',
      endDate: '2025-10-21 10:00:00',
      amount: '100856.00',
      remark: '备注'
    },
    properties: [
      {
        label: '合同名称',
        getValue: (item) => item.name,
        itemProps: {
          labelStyle: {
            color: 'red'
          }
        } as DescriptionsItemProps
      },
      {
        label: '合同编号',
        getValue: (item) => item.code
      },
      {
        label: '城市',
        getValue: (item) => item.city
      },
      {
        label: '地址',
        getValue: (item) => item.address,
        shouldDisplay: (item) => item.type === '1'
      },
      {
        label: '类型',
        getValue: (item) => item.type
      },
      {
        label: '状态',
        getValue: (item) => item.status
      },
      {
        label: '开始日期',
        getValue: (item) => item.startDate
      },
      {
        label: '结束日期',
        getValue: (item) => item.endDate
      },
      {
        label: '金额',
        getValue: (item) => item.amount,
        unit: '万元'
      },
      {
        label: '备注',
        getValue: (item) => item.remark
      }
    ]
  }
}

关于使用:

<GeneralInfo dataSource={dataSource} properties={properties} />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值