skyline-console/docs/zh/develop/3-10-FormItem-introduction.md

33 KiB
Raw Blame History

简体中文 | English

用途

  • 表单中每个表单项的配置
  • 一般只需要配置type等少量参数即可使用
  • Form组件会基于每个formItem的配置对输入的数值进行相应的验证
  • Form验证不通过将无法点击确认下一步按钮

如何使用

  • 每个表单项包含通用型配置

    • name,表单项的key值,必须项,且唯一,表单项的值在验证通过后保存在form.values[name]

    • label,表单项左侧的标签

    • required, 可选项,默认值为false,值为true时为必填项

    • hidden, 当前表单项是否可隐藏,默认值为false

    • onChange,当前表单项变更时触发的函数

    • extra,表单想下方的说明文字

      • 以创建网络src/pages/network/containers/Network/actions/CreateNetwork.jsx为例

        {
          name: 'mtu',
          label: t('MTU'),
          type: 'input-number',
          min: 68,
          max: 9000,
          extra: t('Minimum value is 68 for IPv4, and 1280 for IPv6.'),
        }
        

        extra

    • tip,表单项左侧标签旁边的问号悬停时显示的内容

      • 以创建云主机src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx为例

        {
          name: 'availableZone',
          label: t('Available Zone'),
          type: 'select',
          placeholder: t('Please select'),
          isWrappedValue: true,
          required: true,
          options: this.availableZones,
          tip: t(
            'Availability zone refers to a physical area where power and network are independent of each other in the same area. In the same region, the availability zone and the availability zone can communicate with each other in the intranet, and the available zones can achieve fault isolation.'
          ),
        }
        

        tip

    • validator,验证表单的数值是否符合要求

      • 返回Promise

      • 以裸机节点创建端口src/pages/compute/containers/BareMetalNode/Detail/Port/actions/Create.jsx为例

        export const macAddressValidate = (rule, value) => {
          if (isMacAddress(value.toUpperCase())) {
            return Promise.resolve(true);
          }
          return Promise.reject(new Error(`${t('Invalid: ')}${macAddressMessage}`));
        };
        {
          name: 'address',
          label: t('MAC Address'),
          required: true,
          type: 'input',
          validator: macAddressValidate,
        }
        
    • component,直接使用component中的组件,而不是使用type配置的组件

      • 以云主机修改配置src/pages/compute/containers/Instance/actions/Resize.jsx为例

        • 直接展示云主机类型选择组件
        {
          name: 'newFlavor',
          label: t('Flavor'),
          component: (
            <FlavorSelectTable flavor={flavor} onChange={this.onFlavorChange} />
          ),
          required: true,
          wrapperCol: {
            xs: {
              span: 24,
            },
            sm: {
              span: 18,
            },
          },
        }
        
    • labelCol,调整表单项标题的布局,默认使用Form下定义的标签布局

      • 以项目管理配额src/pages/identity/containers/Project/actions/QuotaManager.jsx为例

        {
          name: 'instances',
          label: t('instance'),
          type: 'input-number',
          labelCol: { span: 12 },
          colNum: 2,
          validator: this.checkMin,
        }
        

        labelCol

    • wrapperCol,调整表单项右侧的布局,默认使用Form下定义的布局

      • 以云主机修改配置src/pages/compute/containers/Instance/actions/Resize.jsx为例

        • 直接展示云主机类型选择组件
        {
          name: 'newFlavor',
          label: t('Flavor'),
          component: (
            <FlavorSelectTable flavor={flavor} onChange={this.onFlavorChange} />
          ),
          required: true,
          wrapperCol: {
            xs: {
              span: 24,
            },
            sm: {
              span: 18,
            },
          },
        }
        

        wrapperCol

    • style,定义表单项的样式

      • 以创建虚拟网卡src/pages/network/containers/VirtualAdapter/actions/Create.jsx为例

        {
          name: 'ipv6',
          label: 'IPv6',
          type: 'label',
          style: { marginBottom: 24 },
          content: (
            <span>
              {t('The selected VPC/ subnet does not have IPv6 enabled.')}{' '}
              <Button type="link">
                {t('To open')} <FormOutlined />
              </Button>{' '}
            </span>
          ),
          hidden: true,
        }
        
    • dependencies,依赖项,数组,依赖项的数值变动后,会触发当前表单项的验证

      • 以云主机更新密码src/pages/compute/containers/Instance/actions/ChangePassword.jsx为例

        • 确认密码的验证,要依赖于密码的输入
        {
          name: 'confirmPassword',
          label: t('Confirm Password'),
          type: 'input-password',
          dependencies: ['password'],
          required: true,
          otherRule: getPasswordOtherRule('confirmPassword', 'instance'),
        },
        
    • otherRule,额外的验证规则

  • 每个表单根据自己的type有独属于自身的配置项,目前支持的type

    • label

      • 展示内容使用

      • iconType属性,可以显示资源对应的 icon

        const iconTypeMap = {
          instance: <DesktopOutlined />,
          router: <BorderOuterOutlined />,
          externalNetwork: <GlobalOutlined />,
          network: <GlobalOutlined />,
          firewall: <SecurityScanOutlined />,
          volume: <InboxOutlined />,
          gateway: <GatewayOutlined />,
          user: <UserOutlined />,
          snapshot: <CameraOutlined />,
          backup: <SaveOutlined />,
          keypair: <KeyOutlined />,
          image: ImageIcon,
          aggregate: <ClusterOutlined />,
          metadata: <TagOutlined />,
          flavor: <HddOutlined />,
          host: <CloudServerOutlined />,
        };
        
        • 以云主机挂载云硬盘src/pages/compute/containers/Instance/actions/AttachVolume.jsx为例

          {
            name: 'instance',
            label: t('Instance'),
            type: 'label',
            iconType: 'instance',
          },
          

          label

      • content属性,默认是基于name属性展示内容,如果具有content属性,则依照content展示内容

        • content可以是字符串,也可以是 ReactNode

        • 以虚拟网卡修改 QoSsrc/pages/network/containers/VirtualAdapter/actions/ModifyQoS.jsx为例

          {
            name: 'name',
            label: t('Current QoS policy name'),
            type: 'label',
            content: <div>{qosPolicy.name || t('Not yet bound')}</div>,
            hidden: !enableQosPolicy,
          }
          
    • input

      • 输入框

      • 以编辑镜像src/pages/compute/containers/Image/actions/Edit.jsx为例

        • 输入系统版本
        {
          name: 'os_version',
          label: t('OS Version'),
          type: 'input',
          required: true,
        },
        

        input

    • select

      • 选择

      • options,必须项,option数组,每个option需要具有如下属性

        • value,值
        • label,展示的文本
      • 以创建云主机选择可用域src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx为例

        get availableZones() {
          return (globalAvailabilityZoneStore.list.data || [])
            .filter((it) => it.zoneState.available)
            .map((it) => ({
              value: it.zoneName,
              label: it.zoneName,
            }));
        }
        
        {
          name: 'availableZone',
          label: t('Available Zone'),
          type: 'select',
          placeholder: t('Please select'),
          isWrappedValue: true,
          required: true,
          options: this.availableZones,
          tip: t(
            'Availability zone refers to a physical area where power and network are independent of each other in the same area. In the same region, the availability zone and the availability zone can communicate with each other in the intranet, and the available zones can achieve fault isolation.'
          ),
        },
        

        select

      • isWrappedValue,表示表单项的值中是否要包含option信息

        • 默认值为false,值为选中的option中的value
        • 如果设为true,值为选中的option
    • divider

      • 横线分隔符

      • 以创建云主机src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx为例

        {
          type: 'divider',
        }
        

        divider

    • radio

      • 单选

      • options,必须项,option数组,每个option需要具有如下属性

        • value,值
        • label,展示的文本
      • 以创建云主机选择登陆凭证类型src/pages/compute/containers/Instance/actions/StepCreate/SystemStep/index.jsx为例

        get loginTypes() {
          return [
            {
              label: t('Keypair'),
              value: 'keypair',
              disabled: this.isWindowsImage,
            },
            {
              label: t('Password'),
              value: 'password',
            },
          ];
        }
        
        {
          name: 'loginType',
          label: t('Login Type'),
          type: 'radio',
          options: this.loginTypes,
          isWrappedValue: true,
        },
        

        radio

      • isWrappedValue,表示表单项的值中是否要包含option信息

        • 默认值为false,值为选中的option中的value
        • 如果设为true,值为选中的option
    • select-table

      • 带有选择操作的表格

      • isMulti,是否是多选,默认为false

      • datas,数据源,使用前端分页时使用

      • columns,表格列的配置,配置方式同BaseList

      • filterParams,搜索项的配置

      • pageSize,每页条目数量,默认为 5

      • disabledFunc,判定哪些条目不可选

      • selectedLabel,表格底部的标签,默认为已选

      • header,表格上方的内容

      • backendPageStore,使用后端分页时,数据对应的store

      • backendPageFunc,使用后端分页时,获取数据的方法,默认为fetchListByPage

      • backendPageDataKey,使用后端分页时,数据在store中的位置,默认为list

      • extraParams,使用后端分页时,发起请求时的额外参数

      • isSortByBack,是否使用后端排序,默认为false

      • defaultSortKey,使用后端排序时,默认的排序键

      • defaultSortOrder,使用后端排序时,默认的排序方向

      • initValue,初始值

      • rowKey,数据的唯一标识,默认为id

      • onRow,点击条目时的操作,默认点击条目就会选中该条目

      • tabstab 型的表格

      • defaultTabValuetab 型表格时,默认的 tab

      • onTabChangetab 型表格时tab 切换时,调用的函数

      • 以创建云主机选择安全组src/pages/compute/containers/Instance/actions/StepCreate/NetworkStep/index.jsx为例

        • 这个表格的右侧标题有 tip 提示
        • 使用后端分页的方式展示数据,并具有额外的参数
        • 是多选
        • 这个表格的上方有额外的展示内容
        • 需要复写onRow属性,以免点击表格中的查看规则按钮时产生操作冲突
        {
          name: 'securityGroup',
          label: t('Security Group'),
          type: 'select-table',
          tip: t(
            'Each instance belongs to at least one security group, which needs to be specified when it is created. Instances in the same security group can communicate with each other on the network, and instances in different security groups are disconnected from the internal network by default.'
          ),
          backendPageStore: this.securityGroupStore,
          extraParams: { project_id: this.currentProjectId },
          required: true,
          isMulti: true,
          header: (
            <div style={{ marginBottom: 8 }}>
              {t(
                'The security group is similar to the firewall function and is used to set up network access control. '
              )}
              {t(' You can go to the console to ')}
              <Link to="/network/security-group">
                {t('create a new security group')}&gt;{' '}
              </Link>
              {t(
                'Note: The security group you use will act on all virtual adapters of the instance.'
              )}
            </div>
          ),
          filterParams: securityGroupFilter,
          columns: securityGroupColumns,
          onRow: () => {},
        },
        

        select-table

      • 以创建云硬盘选择镜像src/pages/storage/containers/Volume/actions/Create/index.jsx为例

        • 这是带有 Tab 标签的表格,默认展示第一个 tabtab 切换时会更新数据源
        • 数据使用前端分页的方式获取,直接配置datas即可
        • 是单选
        • 配置了已选标签为已选 镜像
        {
          name: 'image',
          label: t('Operating System'),
          type: 'select-table',
          datas: this.images,
          required: sourceTypesIsImage,
          isMulti: false,
          hidden: !sourceTypesIsImage,
          filterParams: [
            {
              label: t('Name'),
              name: 'name',
            },
          ],
          columns: getImageColumns(this),
          tabs: this.systemTabs,
          defaultTabValue: this.systemTabs[0].value,
          selectedLabel: t('Image'),
          onTabChange: this.onImageTabChange,
        }
        

        select-table-tabs

    • input-number

      • 数字输入框

      • min,最小值

      • max,最大值

      • 以创建网络设置 MTUsrc/pages/network/containers/Network/actions/CreateNetwork.jsx为例

        • 设置了最小、最大值
        {
          name: 'mtu',
          label: t('MTU'),
          type: 'input-number',
          min: 68,
          max: 9000,
          extra: t('Minimum value is 68 for IPv4, and 1280 for IPv6.'),
        },
        

        input-number

    • input-int

      • 整数输入框

      • min,最小值

      • max,最大值

      • 以创建镜像设置最小系统盘src/pages/compute/containers/Image/actions/Create.jsx为例

        • 设置了最小、最大值
        {
          name: 'min_disk',
          label: t('Min System Disk(GB)'),
          type: 'input-int',
          min: 0,
          max: 500,
        }
        

        input-int

    • instance-volume

      • 云主机硬盘配置组件

      • options,云硬盘类型的选项

      • minSize,云硬盘大小输入框的最小值

      • 以创建云主机配置系统盘src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx为例

        {
          name: 'systemDisk',
          label: t('System Disk'),
          type: 'instance-volume',
          options: this.volumeTypes,
          required: !this.sourceTypeIsVolume,
          hidden: this.sourceTypeIsVolume,
          validator: this.checkSystemDisk,
          minSize: this.getSystemDiskMinSize(),
          extra: t('Disk size is limited by the min disk of flavor, image, etc.'),
          onChange: this.onSystemDiskChange,
        }
        

        instance-volume

    • input-password

      • 密码输入框

      • 以创建云主机输入密码src/pages/compute/containers/Instance/actions/StepCreate/SystemStep/index.jsx为例

        • 输入密码,确认密码,并要验证密码格式,以及两次输入数据的一致性
        {
          name: 'password',
          label: t('Login Password'),
          type: 'input-password',
          required: isPassword,
          hidden: !isPassword,
          otherRule: getPasswordOtherRule('password', 'instance'),
        },
        {
          name: 'confirmPassword',
          label: t('Confirm Password'),
          type: 'input-password',
          required: isPassword,
          hidden: !isPassword,
          otherRule: getPasswordOtherRule('confirmPassword', 'instance'),
        },
        

        input-password

    • input-name

      • 带有格式验证的名称输入框

      • placeholder,输入框的提示语

      • isFile,以文件格式验证名称

      • isKeypair,以密钥支持的格式验证名称

      • isStack,以堆栈支持的格式验证名称

      • isImage,以镜像支持的格式验证名称

      • isInstance,以云主机支持的格式验证名称

      • 以创建云主机输入名称src/pages/compute/containers/Instance/actions/StepCreate/SystemStep/index.jsx为例

        • 输入密码,确认密码,并要验证密码格式,以及两次输入数据的一致性
        {
          name: 'name',
          label: t('Name'),
          type: 'input-name',
          placeholder: t('Please input name'),
          required: true,
          isInstance: true,
        }
        

        input-name

    • port-range

      • 带有验证的 port 输入框

      • 以安全组创建规则设置源端口/端口范围src/pages/network/containers/SecurityGroup/Detail/Rule/actions/Create.jsx为例

        {
          name: 'sourcePort',
          label: t('Source Port/Port Range'),
          type: 'port-range',
          required: showSourcePort,
          hidden: !showSourcePort,
        }
        

        port-range

    • more

      • 隐藏/展示更多配置项按钮

      • 以创建云主机系统配置src/pages/compute/containers/Instance/actions/StepCreate/SystemStep/index.jsx为例

        {
          name: 'more',
          label: t('Advanced Options'),
          type: 'more',
        }
        

        more

    • textarea

      • 多行文本输入框

      • 以编辑云硬盘设置描述src/pages/storage/containers/Volume/actions/Edit.jsx为例

        {
          name: 'description',
          label: t('Description'),
          type: 'textarea',
        }
        

        textarea

    • upload

      • 上传文件输入框

      • 以创建镜像上传镜像文件src/pages/compute/containers/Image/actions/Create.jsx为例

        {
          name: 'file',
          label: t('File'),
          type: 'upload',
          required: true,
        }
        

        upload

    • add-select

      • 可以添加、删除条目的表单项

      • minCount,最小数量

      • maxCount,最多数量

      • itemComponent,增加的每个条目使用的组件

      • defaultItemValue,新增条目的默认值

      • addText,添加条目按钮右侧的文字

      • addTextTips,如果maxCount存在,随着条目数量的变更,显示的文字

      • 以创建云主机设置数据盘src/pages/compute/containers/Instance/actions/StepCreate/BaseStep/index.jsx为例

        • 可以设置任意个数的数据盘
        {
          name: 'dataDisk',
          label: t('Data Disk'),
          type: 'add-select',
          options: this.volumeTypes,
          defaultItemValue: this.defaultVolumeType,
          itemComponent: InstanceVolume,
          minCount: 0,
          addTextTips: t('Data Disks'),
          addText: t('Add Data Disks'),
          extra: t(
            'Too many disks mounted on the instance will affect the read and write performance. It is recommended not to exceed 16 disks.'
          ),
          onChange: this.onDataDiskChange,
        },
        

        add-select

    • ip-input

      • 带有验证功能的 IP 输入框

      • versionip 类型,默认是4,还可设置为6

      • 以云主机挂载网卡手动指定 IPsrc/pages/compute/containers/Instance/actions/AttachInterface.jsx为例

        {
          name: 'ip',
          label: t('Given IP'),
          type: 'ip-input',
          required: ipType === 1,
          hidden: ipType !== 1,
          version,
          // defaultIp,
          validator: this.checkIP,
          extra: t('Please make sure this IP address be available.'),
        }
        

        ip-input

    • member-allocator

      • 负载均衡器中使用的成员选择表单

      • 以负载均衡器配置成员src/pages/network/containers/LoadBalancers/StepCreateComponents/MemberStep/index.jsx为例

        {
          name: 'extMembers',
          type: 'member-allocator',
          isLoading: this.store.list.isLoading,
          ports: this.state.ports,
        }
        

        member-allocator

    • descriptions

      • 展示多种信息的表单项

      • title,右侧内容的标题

      • onClick,右侧内容标题旁的跳转按钮

      • items,每个信息展示项的配置,数组

        • label,信息展示项左侧的标题文字
        • value,信息展示项右侧的值
        • span,信息展示右侧占用的布局尺寸
      • 以创建云主机确认src/pages/compute/containers/Instance/actions/StepCreate/ConfirmStep/index.jsx为例

        {
          name: 'confirm-config',
          label: t('Config Overview'),
          type: 'descriptions',
          title: t('Base Config'),
          onClick: () => {
            this.goStep(0);
          },
          items: [
            {
              label: t('Start Source'),
              value: context.source.label,
            },
            {
              label: t('System Disk'),
              value: this.getSystemDisk(),
            },
            {
              label: t('Available Zone'),
              value: context.availableZone.label,
            },
            {
              label: t('Start Source Name'),
              value: this.getSourceValue(),
            },
            {
              label: t('Data Disk'),
              value: this.getDataDisk(),
            },
            {
              label: t('Project'),
              value: context.project,
            },
            {
              label: t('Flavor'),
              value: this.getFlavor(),
            },
          ],
        }
        

        descriptions

    • slider-input

      • 滑动与输入联动的表单项

      • min,最小值

      • max,最大值

      • description,滑动条下的描述语

      • 以创建云硬盘设置容量src/pages/storage/containers/Volume/actions/Create/index.jsx为例

        {
          name: 'size',
          label: t('Capacity (GB)'),
          type: 'slider-input',
          max: this.maxSize,
          min: minSize,
          description: `${minSize}GB-${this.maxSize}GB`,
          required: this.quotaIsLimit,
          hidden: !this.quotaIsLimit,
          onChange: this.onChangeSize,
        },
        

        slider-input

    • title

      • 展示标题

      • 以创建堆栈配置参数src/pages/heat/containers/Stack/actions/Create/Parameter.jsx为例

        {
          label: t('Fill In The Parameters'),
          type: 'title',
        }
        

        title

    • switch

      • 开关

      • 以创建虚拟网卡设置安全组src/pages/network/containers/VirtualAdapter/actions/Create.jsx为例

        {
          name: 'port_security_enabled',
          label: t('Port Security'),
          type: 'switch',
          tip: t(
            'Disabling port security will turn off the security group policy protection and anti-spoofing protection on the port. General applicable scenarios: NFV or operation and maintenance Debug.'
          ),
          onChange: (e) => {
            this.setState({
              port_security_enabled: e,
            });
          },
        }
        

        switch

    • check

      • checkbox

      • content,输入框右侧的文字

      • 以云主机修改配置是否强制关机src/pages/compute/containers/Instance/actions/Resize.jsx为例

        {
          name: 'option',
          label: t('Forced Shutdown'),
          type: 'check',
          content: t('Agree to force shutdown'),
          required: true,
        },
        

        check

    • transfer

      • 穿梭框

      • leftTableColumns,左侧表格的列配置

      • rightTableColumns,右侧表格的列配置

      • dataSource,可供选择的数据源

      • showSearch,是否显示搜索输入框

      • oriTargetKeys,初始化的选中值

      • disabled,是否禁用左侧数据的选中,默认为false

      • 以用户编辑系统角色src/pages/identity/containers/User/actions/SystemRole.jsx为例

        • 左侧是项目名称列表
        • 右侧是项目名称、对项目配置的角色信息列表
        {
          name: 'select_project',
          type: 'transfer',
          label: t('Project'),
          leftTableColumns: this.leftUserTable,
          rightTableColumns: this.rightUserTable,
          dataSource: this.projectList
            ? this.projectList.filter((it) => it.domain_id === domainDefault)
            : [],
          disabled: false,
          showSearch: true,
          oriTargetKeys: projectRoles ? Object.keys(projectRoles) : [],
        }
        

        transfer

    • check-group

      • checkbox 组

      • options,配置每个checkbox的信息

        • label,每个checkbox对应的文字
        • valuecheckbox对应的键
      • 以编辑元数据src/pages/configuration/containers/Metadata/actions/Edit.jsx为例

        • 配置 公有、受保护的 属性
        {
          name: 'options',
          label: t('Options'),
          type: 'check-group',
          options: [
            { label: t('Public'), value: 'isPublic' },
            { label: t('Protected'), value: 'isProtected' },
          ],
        }
        

        check-group

    • textarea-from-file

      • 带有读取文件功能的多行文本输入框

      • 选择文件后,会将文件的内容读取到文本输入框中

      • 以创建密钥输入公钥信息src/pages/compute/containers/Keypair/actions/Create.jsx为例

        • 配置 公有、受保护的 属性
        {
          name: 'public_key',
          label: t('Public Key'),
          type: 'textarea-from-file',
          hidden: isCreate,
          required: !isCreate,
        }
        

        textarea-from-file

    • ip-distributer

      • IP 输入框

      • subnets,选择子网后配置 IP 信息

      • 可以自动分配 IP也可手动指定 IP

      • 可以添加多个 IP

      • 以创建虚拟网卡设置 IPsrc/pages/network/containers/VirtualAdapter/actions/Create.jsx为例

        {
          name: 'fixed_ips',
          label: t('Owned Subnet'),
          type: 'ip-distributer',
          subnets: subnetDetails,
          hidden: !network_id,
          required: true,
        }
        

        ip-distributer

    • mac-address

      • mac 地址输入框

      • 支持自动分配,也可手动指定

      • 以编辑虚拟网卡设置 MAC 地址src/pages/network/containers/VirtualAdapter/actions/Edit.jsx为例

        {
          name: 'mac_address',
          label: t('Mac Address'),
          wrapperCol: { span: 16 },
          type: 'mac-address',
          required: true,
        }
        

        mac-address

    • network-select-table

      • 选择网络的表单项

      • 分 Tab 展示当前项目网络、共享网络,如果用户具有管理员角色,还可展示全部网络

      • 以创建虚拟网卡设置网络src/pages/network/containers/VirtualAdapter/actions/Create.jsx为例

        {
          name: 'network_id',
          label: t('Owned Network'),
          type: 'network-select-table',
          onChange: this.handleOwnedNetworkChange,
          required: true,
        },
        

        network-select-table

    • volume-select-table

      • 选择硬盘的表单项

      • 分 Tab 展示可用的、共享的云硬盘

      • disabledFunc,配置什么样的云硬盘不可选

      • 以云主机挂载硬盘选择硬盘src/pages/compute/containers/Instance/actions/AttachVolume.jsx为例

        {
          name: 'volume',
          label: t('Volume'),
          type: 'volume-select-table',
          tip: multiTip,
          isMulti: false,
          required: true,
          serverId: this.item.id,
          disabledFunc: (record) => {
            const diskFormat = _get(
              record,
              'origin_data.volume_image_metadata.disk_format'
            );
            return diskFormat === 'iso';
          },
        }
        

        volume-select-table

    • tab-select-table

      • 带有 Tab 的表格型选择表单项

      • isMulti,配置是否为多选

      • 以申请浮动 IP 选择 Qossrc/pages/network/containers/FloatingIp/actions/Allocate.jsx为例

        • 分当前项目、共享的 QoS如果用户具有管理员权限也具有所有 QoS 标签项
        {
          name: 'qos_policy_id',
          label: t('QoS Policy'),
          type: 'tab-select-table',
          tabs: getQoSPolicyTabs.call(this),
          isMulti: false,
          tip: t('Choosing a QoS policy can limit bandwidth and DSCP'),
          onChange: this.onQosChange,
        }
        

        tab-select-table

    • metadata-transfer

      • 编辑元数据的表单项

      • 以镜像编辑元数据src/pages/compute/containers/Image/actions/ManageMetadata.jsx为例

        {
          name: 'systems',
          label: t('Metadata'),
          type: 'metadata-transfer',
          metadatas: this.metadatas,
          validator: (rule, value) => {
            if (this.hasNoValue(value)) {
              return Promise.reject(t('Please input value'));
            }
            return Promise.resolve();
          },
        }
        

        metadata-transfer

    • aceEditor

      • aceEditor

      • 以创建虚拟网卡编辑 Profilesrc/pages/network/containers/VirtualAdapter/actions/Create.jsx为例

        {
          name: 'bindingProfile',
          label: t('Binding Profile'),
          type: 'aceEditor',
          hidden: !more,
          mode: 'json',
          wrapEnabled: true,
          tabSize: 2,
          width: '100%',
          height: '200px',
          setOptions: {
            enableBasicAutocompletion: true,
            enableLiveAutocompletion: true,
            enableSnippets: true,
          },
          validator: (item, value) => {
            if (value !== undefined && value !== '') {
              try {
                JSON.parse(value);
                return Promise.resolve(true);
              } catch (e) {
                return Promise.reject(new Error(t('Illegal JSON scheme')));
              }
            }
            return Promise.resolve(true);
          },
        }
        

        aceEditor

    • input-json

      • 带有 json 格式验证的输入框

      • 以创建堆栈编辑参数为例src/resources/stack.js为例

        export const getFormItemType = (type) => {
          switch (type) {
            case 'number':
              return {
                type: 'input-number',
              };
            case 'json':
              return {
                type: 'input-json',
              };
            case 'boolean':
              return {
                type: 'radio',
                options: yesNoOptions,
              };
            default:
              return {
                type: 'input',
              };
          }
        };
        

        input-json