API 参考

fieldsConfig 配置详解

SmartCrudPage 和 SmartForm 的字段配置完整 API


🎯 概述

fieldsConfig 是 NextJS Base 的核心配置,一份配置驱动表格、表单、搜索、详情四个场景。


📋 基础结构

interface FieldConfig {
  key: string           // 字段名(必填)
  title: string         // 显示标题(必填)
  type: FieldType       // 字段类型(必填)
  options?: Option[] | (() => Promise<Option[]>)  // 选项
  table?: TableConfig   // 表格配置
  form?: FormConfig     // 表单配置
  search?: SearchConfig // 搜索配置
}

🔤 字段类型 (type)

类型说明表格表单搜索
text单行文本Input
textarea多行文本TextArea
number数字InputNumber
select下拉选择Select
switch开关Switch
date日期DatePicker
datetime日期时间DateTimePicker
tree-select树形选择TreeSelect
icon图标IconPicker
image单图ImageUpload
images多图MultiImageUpload
markdownMarkdownMarkdownEditor
jsonJSONJsonEditor

📊 表格配置 (table)

interface TableConfig {
  // 显示控制
  width?: number              // 列宽
  fixed?: 'left' | 'right'    // 固定列
  hidden?: boolean            // 是否隐藏
  
  // 文本显示
  ellipsis?: boolean          // 超长省略
  copyable?: boolean          // 可复制
  
  // 排序
  sorter?: boolean            // 启用排序
  defaultSortOrder?: 'ascend' | 'descend'  // 默认排序
  
  // 自定义渲染
  render?: (value: any, record: any, index: number) => ReactNode
  
  // 值映射(用于状态显示)
  valueEnum?: Record<string, {
    text: string
    status?: 'Success' | 'Error' | 'Processing' | 'Warning' | 'Default'
    color?: string
  }>
}

示例

// 基础配置
{
  key: 'name',
  title: '名称',
  type: 'text',
  table: {
    width: 200,
    ellipsis: true,
    copyable: true,
  },
}

// 固定列
{
  key: 'id',
  title: 'ID',
  type: 'text',
  table: {
    width: 80,
    fixed: 'left',
  },
}

// 排序
{
  key: 'createdAt',
  title: '创建时间',
  type: 'datetime',
  table: {
    width: 180,
    sorter: true,
    defaultSortOrder: 'descend',
  },
}

// 状态映射
{
  key: 'status',
  title: '状态',
  type: 'select',
  table: {
    width: 100,
    valueEnum: {
      active: { text: '启用', status: 'Success' },
      inactive: { text: '禁用', status: 'Error' },
      pending: { text: '待审核', status: 'Processing' },
    },
  },
}

// 自定义渲染
{
  key: 'price',
  title: '价格',
  type: 'number',
  table: {
    width: 120,
    render: (value) => `¥${value?.toFixed(2) || '0.00'}`,
  },
}

// 隐藏列
{
  key: 'remark',
  title: '备注',
  type: 'textarea',
  table: {
    hidden: true,  // 表格中不显示
  },
}

📝 表单配置 (form)

interface FormConfig {
  // 显示控制
  hidden?: boolean            // 是否隐藏
  disabled?: boolean          // 是否禁用
  readonly?: boolean          // 是否只读
  
  // 验证
  required?: boolean          // 是否必填
  rules?: Rule[]              // 验证规则
  
  // 默认值
  defaultValue?: any
  
  // 输入提示
  placeholder?: string
  tooltip?: string            // 帮助图标提示
  extra?: string              // 额外说明文字
  
  // 布局
  colSpan?: number            // 列宽 (1-24)
  
  // 字段联动
  dependencies?: string[]     // 依赖字段
  visible?: (form: FormInstance) => boolean  // 动态显示
  fieldProps?: (form: FormInstance) => object  // 动态属性
  
  // 特定类型配置
  rows?: number               // textarea 行数
  min?: number                // number 最小值
  max?: number                // number 最大值
  step?: number               // number 步长
  precision?: number          // number 精度
  prefix?: string             // 前缀
  suffix?: string             // 后缀
  maxCount?: number           // 图片最大数量
  accept?: string             // 文件类型
  maxSize?: number            // 文件大小限制 (MB)
}

示例

// 必填文本
{
  key: 'name',
  title: '名称',
  type: 'text',
  form: {
    required: true,
    placeholder: '请输入名称',
    rules: [
      { min: 2, message: '至少 2 个字符' },
      { max: 50, message: '最多 50 个字符' },
    ],
  },
}

// 数字输入
{
  key: 'price',
  title: '价格',
  type: 'number',
  form: {
    required: true,
    min: 0,
    max: 99999,
    precision: 2,
    prefix: '¥',
    placeholder: '请输入价格',
  },
}

// 多行文本
{
  key: 'description',
  title: '描述',
  type: 'textarea',
  form: {
    rows: 4,
    maxLength: 500,
    showCount: true,
    placeholder: '请输入描述信息',
  },
}

// 开关
{
  key: 'enable',
  title: '是否启用',
  type: 'switch',
  form: {
    defaultValue: true,
    checkedChildren: '开',
    unCheckedChildren: '关',
  },
}

// 图片上传
{
  key: 'avatar',
  title: '头像',
  type: 'image',
  form: {
    maxCount: 1,
    accept: 'image/*',
    maxSize: 2,
    tip: '支持 jpg、png 格式,最大 2MB',
  },
}

// 字段联动
{
  key: 'discountType',
  title: '优惠类型',
  type: 'select',
  options: [
    { label: '固定金额', value: 'fixed' },
    { label: '百分比', value: 'percent' },
  ],
},
{
  key: 'discountValue',
  title: '优惠值',
  type: 'number',
  form: {
    dependencies: ['discountType'],
    fieldProps: (form) => ({
      suffix: form.getFieldValue('discountType') === 'percent' ? '%' : '元',
      max: form.getFieldValue('discountType') === 'percent' ? 100 : undefined,
    }),
  },
}

// 条件显示
{
  key: 'reason',
  title: '拒绝原因',
  type: 'textarea',
  form: {
    dependencies: ['status'],
    visible: (form) => form.getFieldValue('status') === 'rejected',
    required: (form) => form.getFieldValue('status') === 'rejected',
  },
}

// 隐藏字段
{
  key: 'id',
  title: 'ID',
  type: 'text',
  form: {
    hidden: true,
  },
}

interface SearchConfig {
  enabled?: boolean           // 是否启用搜索
  mode?: 'like' | 'exact' | 'in' | 'range'  // 搜索模式
  placeholder?: string        // 占位符
  defaultValue?: any          // 默认值
}

搜索模式详解

模式说明适用类型Prisma 转换
like模糊匹配text, textarea{ contains: value }
exact精确匹配select, switch, numbervalue
in多选匹配select (多选){ in: values }
range范围匹配date, datetime, number{ gte: start, lte: end }

示例

// 模糊搜索
{
  key: 'title',
  title: '标题',
  type: 'text',
  search: {
    enabled: true,
    mode: 'like',
    placeholder: '搜索标题',
  },
}

// 精确匹配
{
  key: 'status',
  title: '状态',
  type: 'select',
  options: [
    { label: '启用', value: 'active' },
    { label: '禁用', value: 'inactive' },
  ],
  search: {
    enabled: true,
    mode: 'exact',
  },
}

// 多选匹配
{
  key: 'tags',
  title: '标签',
  type: 'select',
  options: [...],
  search: {
    enabled: true,
    mode: 'in',
  },
}

// 日期范围
{
  key: 'createdAt',
  title: '创建时间',
  type: 'datetime',
  search: {
    enabled: true,
    mode: 'range',
  },
}

// 数字范围
{
  key: 'price',
  title: '价格',
  type: 'number',
  search: {
    enabled: true,
    mode: 'range',
  },
}

🎨 选项配置 (options)

静态选项

{
  key: 'status',
  title: '状态',
  type: 'select',
  options: [
    { label: '启用', value: 'active' },
    { label: '禁用', value: 'inactive' },
  ],
}

动态选项

{
  key: 'categoryId',
  title: '分类',
  type: 'select',
  options: async () => {
    const res = await getCategoryListAction()
    return res.data.map(item => ({
      label: item.name,
      value: item.id,
    }))
  },
}

树形选项

{
  key: 'parentId',
  title: '父级',
  type: 'tree-select',
  options: async () => {
    const res = await getCategoryTreeAction()
    return res.data  // 需要是树形结构
  },
}

📚 完整示例

const fieldsConfig = [
  // ID
  {
    key: 'id',
    title: 'ID',
    type: 'text',
    table: { width: 80, fixed: 'left', copyable: true },
    form: { hidden: true },
  },
  
  // 名称
  {
    key: 'name',
    title: '名称',
    type: 'text',
    table: { width: 200, ellipsis: true },
    form: { required: true, placeholder: '请输入名称' },
    search: { enabled: true, mode: 'like' },
  },
  
  // 分类
  {
    key: 'categoryId',
    title: '分类',
    type: 'select',
    options: async () => {
      const res = await getCategoryListAction()
      return res.data.map(item => ({ label: item.name, value: item.id }))
    },
    table: { width: 120 },
    form: { required: true },
    search: { enabled: true, mode: 'exact' },
  },
  
  // 价格
  {
    key: 'price',
    title: '价格',
    type: 'number',
    table: {
      width: 100,
      sorter: true,
      render: (value) => `¥${value?.toFixed(2)}`,
    },
    form: { required: true, min: 0, precision: 2, prefix: '¥' },
    search: { enabled: true, mode: 'range' },
  },
  
  // 状态
  {
    key: 'enable',
    title: '状态',
    type: 'switch',
    table: {
      width: 80,
      render: (value) => value ? '✅ 启用' : '❌ 禁用',
    },
    form: { defaultValue: true },
    search: { enabled: true, mode: 'exact' },
  },
  
  // 备注
  {
    key: 'remark',
    title: '备注',
    type: 'textarea',
    table: { hidden: true },
    form: { rows: 3 },
  },
  
  // 创建时间
  {
    key: 'createdAt',
    title: '创建时间',
    type: 'datetime',
    table: { width: 180, sorter: true },
    form: { hidden: true },
    search: { enabled: true, mode: 'range' },
  },
]

📚 相关文档