@ant-design/icons#QuestionCircleOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#QuestionCircleOutlined. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
public renderTitleLabel(config: DTGComponentPropertySchema) {
    const titleFragment = (
      <span style={{ marginRight: '6px' }}>
        { config['ui:title'] }
      </span>
    );
    if (config['ui:description']) {
      return (
        <div style={config['ui:titleStyle']}>
          { titleFragment }
          <Popover
            content={<RichText html={config['ui:description'].title} />}
            trigger={config['ui:description'].trigger}
          >
            <QuestionCircleOutlined />
          </Popover>
        </div>
      );
    }
    return (
      <div style={config['ui:titleStyle']}>{ titleFragment }</div>
    );
  }
Example #2
Source File: StatusPage.tsx    From jitsu with MIT License 6 votes vote down vote up
SyncEventsDocsTooltip: React.FC = ({ children }) => {
  const content = (
    <div className="max-w-xs">
      <p>
        Events sent from sources may be multiplexed in order to be sent to different destinations. Therefore, total
        amount of destinations events is greater or equal to the total amount of sources events
      </p>
    </div>
  )
  return (
    <span className="cursor-pointer status-page_info-popover">
      <Tooltip title={content}>{children ? children : <QuestionCircleOutlined />}</Tooltip>
    </span>
  )
}
Example #3
Source File: AppDocumentLink.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
export function AppDocumentLink({
  documentId,
}: AppDocumentLinkProps): React.ReactElement {
  const { t } = useTranslation(NS_BASIC_BRICKS);
  const { currentApp } = useRecentApps();
  const showAppDocumentLink = React.useMemo(
    () => getRuntime().getFeatureFlags()["show-app-document-link"],
    []
  );

  const docLink = currentApp?.id
    ? `/next-documents/apps/${currentApp.id}${
        documentId
          ? `?${new URLSearchParams({
              docId: documentId,
            }).toString()}`
          : `/redirect?${new URLSearchParams({
              redirectToDocHomeIfNotFound: "1",
            }).toString()}`
      }`
    : "/next-documents";

  if (!showAppDocumentLink) {
    return null;
  }

  return (
    <div className={styles.docLinkContainer}>
      <Tooltip title={t(K.HELP)}>
        <Link to={docLink} target="_blank">
          <QuestionCircleOutlined />
        </Link>
      </Tooltip>
    </div>
  );
}
Example #4
Source File: RightContent.tsx    From dashboard with Apache License 2.0 6 votes vote down vote up
GlobalHeaderRight: React.SFC<GlobalHeaderRightProps> = (props) => {
  const { theme, layout } = props;
  let className = styles.right;

  if (theme === 'dark' && layout === 'top') {
    className = `${styles.right}  ${styles.dark}`;
  }

  return (
    <div className={className}>
      <Tooltip title="使用帮助">
        <a
          style={{
            color: 'inherit',
          }}
          target="_blank"
          href="https://www.openscrm.cn"
          className={styles.action}
        >
          <QuestionCircleOutlined />
        </a>
      </Tooltip>
      <StaffAdminAvatarDropdown menu={true} />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
    </div>
  );
}
Example #5
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
private renderOptionItem(option: NonNullable<SelectOptionType>[number]) {
    if (option.icon || option.description) {
      return {
        ...option,
        value: option.value,
        label: (
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            { option.icon && this.iconRender(option.icon) }
            <span>{ option.label }</span>
            { option.description && (
            <Popover content={option.description}>
              <QuestionCircleOutlined style={{ margin: '0 8px' }} />
            </Popover>
            ) }
          </div>
        ),
      };
    }
    return { ...option };
  }
Example #6
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
public render() {
    const config = this.props.schema;
    const uiProps = this.props.schema['ui:props'] || {};

    return (
      <RadioGroup
        {...filterAttributes(uiProps, 'options')}
        defaultValue={config.default as RadioGroupProps['defaultValue']}
        value={this.props.value}
        onChange={(e) => {
          this.props.onChange?.(e.target.value);
        }}
      >
        { (this.options as RadioOptionType[])?.map((option, i) => {
          if (typeof option === 'string') {
            option = { label: option, value: option };
          }
          return (
            <Radio key={i} value={option.value} style={option.style} disabled={option.disabled}>
              { option.label }
              { option.description && (
              <Popover content={option.description}>
                <QuestionCircleOutlined style={{ margin: '0 8px' }} />
              </Popover>
              ) }
            </Radio>
          );
        }) }
      </RadioGroup>
    );
  }
Example #7
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
public render() {
    const config = this.props.schema;
    const uiProps = this.props.schema['ui:props'] || {};

    return (
      <Checkbox.Group
        {...filterAttributes(uiProps, 'options')}
        defaultValue={config.default as CheckboxGroupProps['defaultValue']}
        value={this.props.value}
        onChange={(value) => {
          this.props.onChange?.(value);
        }}
      >
        { (this.options as CheckboxOptionType[])?.map((option, i) => {
          if (typeof option === 'string') {
            option = { label: option, value: option };
          }
          return (
            <Checkbox key={i} value={option.value} style={option.style} disabled={option.disabled}>
              { option.icon && this.iconRender(option.icon) }
              { option.label }
              { option.description && (
                <Popover content={option.description}>
                  <QuestionCircleOutlined style={{ margin: '0 8px' }} />
                </Popover>
              ) }
            </Checkbox>
          );
        }) }
      </Checkbox.Group>
    );
  }
Example #8
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
private renderOptionItem(option: NonNullable<LabeledValue>[number]) {
    if (option.icon || option.description) {
      return {
        ...option,
        value: option.value,
        label: (
          <div style={{ display: 'flex', justifyContent: 'space-between' }}>
            { option.icon && this.iconRender(option.icon) }
            <span>{ option.label }</span>
            { option.description && (
            <Popover content={option.description}>
              <QuestionCircleOutlined style={{ margin: '0 8px' }} />
            </Popover>
            ) }
          </div>
        ),
      };
    }
    return { ...option };
  }
Example #9
Source File: index.tsx    From drip-table with MIT License 6 votes vote down vote up
private renderAttributeItem(schema: DTGComponentPropertySchema, index: number, parentIndex: number) {
    if (!this.visible(schema, index, parentIndex)) { return null; }
    return (
      <Row key={index} style={{ lineHeight: '32px', margin: '6px 0' }}>
        <Col span={8}>
          { schema['ui:title'] }
          {
            schema['ui:description']
              ? (
                <Popover content={<RichText html={schema['ui:description'].title} />}>
                  <QuestionCircleOutlined style={{ marginLeft: '12px', cursor: 'pointer' }} />
                </Popover>
              )
              : null
          }
        </Col>
        <Col span={16}>{ this.renderAttributeComponent(schema, index, parentIndex) }</Col>
      </Row>
    );
  }
Example #10
Source File: BatchExecutorPage.tsx    From yakit with GNU Affero General Public License v3.0 6 votes vote down vote up
YakScriptWithCheckboxLine: React.FC<YakScriptWithCheckboxLineProp> = (props) => {
    const {plugin} = props;
    const script = plugin;

    return <Card
        key={plugin.ScriptName} style={{marginBottom: 6}} size={"small"}
        bodyStyle={{paddingLeft: 12, paddingTop: 8, paddingBottom: 8, paddingRight: 12}}
        hoverable={true}
    >
        <div style={{width: "100%", display: "flex", flexDirection: "row"}}>
            <Checkbox style={{marginBottom: 0}} checked={props.selected} onChange={r => {
                if (r.target.checked) {
                    props.onSelected(plugin)
                } else {
                    props.onUnselected(plugin)
                }
            }}>
                <Space>
                    <OneLine maxWidth={270} overflow={"hidden"} title={plugin.ScriptName}>{plugin.ScriptName}</OneLine>
                    {script.Help && <Button
                        size={"small"} type={"link"} onClick={() => {
                        showModal({
                            width: "40%",
                            title: "Help", content: <>
                                {script.Help}
                            </>
                        })
                    }}
                        icon={<QuestionCircleOutlined/>}/>}
                </Space>
            </Checkbox>
            <div style={{flex: 1, textAlign: "right"}}>
                {script.Author && <Tooltip title={script.Author}>
                    <Button size={"small"} type={"link"} icon={<UserOutlined/>}/>
                </Tooltip>}
            </div>
        </div>
    </Card>
}
Example #11
Source File: OnboardingLayout.tsx    From pali-wallet with MIT License 6 votes vote down vote up
OnboardingLayout: FC<IOnboardingLayout> = ({
  title,
  children,
  tooltipText,
}) => (
  <div className="flex flex-col gap-4 items-center justify-center md:pt-20">
    <LogoHeader />

    <section>
      <div className="flex gap-2 items-center justify-center">
        <span className="text-center text-brand-royalblue text-xl font-bold tracking-normal">
          {title}
        </span>

        {tooltipText && (
          <Tooltip content={tooltipText}>
            <QuestionCircleOutlined className="inline-flex w-3 text-brand-graylight text-sm" />
          </Tooltip>
        )}
      </div>
    </section>

    <section>{children}</section>
  </div>
)
Example #12
Source File: RightContent.tsx    From ant-design-pro-V4 with MIT License 5 votes vote down vote up
GlobalHeaderRight: React.SFC<GlobalHeaderRightProps> = (props) => {
  const { theme, layout } = props;
  let className = styles.right;

  if (theme === 'dark' && layout === 'top') {
    className = `${styles.right}  ${styles.dark}`;
  }

  return (
    <div className={className}>
      <HeaderSearch
        className={`${styles.action} ${styles.search}`}
        placeholder="Site Search"
        defaultValue="umi ui"
        options={[
          { label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
          {
            label: <a href="next.ant.design">Ant Design</a>,
            value: 'Ant Design',
          },
          {
            label: <a href="https://protable.ant.design/">Pro Table</a>,
            value: 'Pro Table',
          },
          {
            label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
            value: 'Pro Layout',
          },
        ]}
        // onSearch={value => {
        //   //console.log('input', value);
        // }}
      />
      <Tooltip title="Use documentation">
        <a
          style={{
            color: 'inherit',
          }}
          target="_blank"
          href="https://pro.ant.design/docs/getting-started"
          rel="noopener noreferrer"
          className={styles.action}
        >
          <QuestionCircleOutlined />
        </a>
      </Tooltip>
      <Avatar />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
      <SelectLang className={styles.action} />
    </div>
  );
}
Example #13
Source File: TAQueueListDetail.tsx    From office-hours with GNU General Public License v3.0 5 votes vote down vote up
PriorityQueueQuestionBubble = styled(QuestionCircleOutlined)`
  margin-right: 8px;
`
Example #14
Source File: ProfileDrawer.tsx    From office-hours with GNU General Public License v3.0 5 votes vote down vote up
export default function ProfileDrawer({
  courseId,
}: ProfileDrawerProps): ReactElement {
  const [isPopoverOpen, setIsPopoverOpen] = useState(false);
  const role = useRoleInCourse(courseId);

  return (
    <>
      <NoPaddingPopover
        content={
          isPopoverOpen && (
            <Menu mode="inline">
              <Menu.Item icon={<SettingOutlined />}>
                <Link
                  href={{ pathname: "/settings", query: { cid: courseId } }}
                >
                  <a>Settings</a>
                </Link>
              </Menu.Item>
              <Menu.Item
                icon={<MacCommandOutlined />}
                onClick={() => {
                  Modal.info({
                    title: "Queue Page Keyboard Shortcuts",
                    content: shortcutInfoContent(role),
                  });
                  setIsPopoverOpen(false);
                }}
              >
                Keyboard Shortcuts
              </Menu.Item>
              <Menu.Item
                key="1"
                icon={<QuestionCircleOutlined />}
                onClick={() => {
                  window.open("https://info.khouryofficehours.com/help");
                  setIsPopoverOpen(false);
                }}
              >
                Help Guide
              </Menu.Item>
              <Menu.Item
                key="2"
                icon={<FileTextOutlined />}
                onClick={() => {
                  window.open(
                    "https://info.khouryofficehours.com/release-notes-archive"
                  );
                  setIsPopoverOpen(false);
                }}
              >
                Release Notes
              </Menu.Item>
              <Menu.Item key="3" icon={<ReadOutlined />}>
                <Link href={"/about"}>
                  <a>About Us</a>
                </Link>
              </Menu.Item>
              <Menu.Item key="4" icon={<LogoutOutlined />}>
                <Link href={"/api/v1/logout"}>
                  <a data-cy="logout-button">Logout</a>
                </Link>
              </Menu.Item>
            </Menu>
          )
        }
        placement="bottomRight"
        trigger="click"
        visible={isPopoverOpen}
        onVisibleChange={setIsPopoverOpen}
      >
        <AvatarButton>
          <SelfAvatar size={40} />
        </AvatarButton>
      </NoPaddingPopover>
    </>
  );
}
Example #15
Source File: CourseAdminPanel.tsx    From office-hours with GNU General Public License v3.0 5 votes vote down vote up
export default function CourseAdminPanel({
  defaultPage,
  courseId,
}: CourseAdminPageProps): ReactElement {
  const profile = useProfile();
  const [currentSettings, setCurrentSettings] = useState(
    defaultPage || CourseAdminOptions.CHECK_IN
  );

  const router = useRouter();

  return (
    <Row>
      <Col span={4} style={{ textAlign: "center" }}>
        <SettingsPanelAvatar avatarSize={20} />
        <CenteredText>
          Welcome back
          <br />
          {profile?.firstName} {profile?.lastName}
          {!profile?.photoURL && (
            <Tooltip
              title={
                "You should consider uploading a profile picture to make yourself more recognizable to students"
              }
            >
              <span>
                <QuestionCircleOutlined
                  style={{ marginLeft: "5px" }}
                  onClick={() => {
                    router.push(`/settings?cid=${courseId}`);
                  }}
                />
              </span>
            </Tooltip>
          )}
        </CenteredText>
        <Menu
          defaultSelectedKeys={[currentSettings]}
          onClick={(e) => setCurrentSettings(e.key as CourseAdminOptions)}
          style={{ background: "#f8f9fb", paddingTop: "20px" }}
        >
          <Menu.Item key={CourseAdminOptions.CHECK_IN} icon={<EditOutlined />}>
            TA Check In/Out Times
          </Menu.Item>
          <Menu.Item key={CourseAdminOptions.OVERRIDES} icon={<BellOutlined />}>
            Course Overrides
          </Menu.Item>
        </Menu>
      </Col>
      <VerticalDivider />
      <Space direction="vertical" size={40} style={{ flexGrow: 1 }}>
        <Col span={20}>
          {currentSettings === CourseAdminOptions.CHECK_IN && (
            <TACheckInCheckOutTimes courseId={courseId} />
          )}
          {currentSettings === CourseAdminOptions.OVERRIDES && (
            <CourseOverrideSettings courseId={courseId} />
          )}
        </Col>
      </Space>
    </Row>
  );
}
Example #16
Source File: FormTableBlocks.tsx    From condo with MIT License 5 votes vote down vote up
function RenderActionsColumn (text, item, index) {
    const intl = useIntl()
    const AreYouSureMessage = intl.formatMessage({ id: 'AreYouSure' })
    const DeleteMessage = intl.formatMessage({ id: 'Delete' })
    const EditMessage = intl.formatMessage({ id: 'Edit' })

    const { user } = useAuth()

    const { isUnsavedNew } = item
    const { action, remove, form, setEditing, setLoading, editing, loading } = _useTableRowForm()

    function validateFields () {
        setLoading(true)
        return form.validateFields()
            .then((values) => action('CreateOrUpdate', { values, item, form }))
            .then(() => (isUnsavedNew) ? remove({ id: item.id }) : null)
            .then(() => (isUnsavedNew) ? null : setEditing(false))
            .finally(() => setLoading(false))
    }

    function deleteRow () {
        setLoading(false)
        setEditing(false)
        remove({ id: item.id })
    }

    return <Space>
        {(isUnsavedNew || editing) ?
            <Button size="small" type={'primary'} onClick={validateFields} loading={loading}>
                <SaveOutlined/>
            </Button>
            : null}
        {(isUnsavedNew) ?
            <Button size="small" type={'primary'} onClick={deleteRow}>
                <DeleteOutlined/>
            </Button>
            :
            <ExtraDropdownActionsMenu actions={[
                (item.user && item.user.id === user.id) ? null : {
                    confirm: {
                        title: AreYouSureMessage,
                        icon: <QuestionCircleOutlined style={{ color: 'red' }}/>,
                    },
                    label: DeleteMessage,
                    action: () => action('Delete', { values: { id: item.id }, item, form }),
                },
                {
                    label: EditMessage,
                    action: () => {
                        setEditing(true)
                    },
                },
            ]}/>
        }
    </Space>
}
Example #17
Source File: LabelWithInfo.tsx    From condo with MIT License 5 votes vote down vote up
LabelWithInfo: React.FC<ILabelWithInfo> = ({ title, message }) => (
    <Tooltip placement='topLeft' title={title}>
        <StyledSpace>
            {message}
            <QuestionCircleOutlined/>
        </StyledSpace>
    </Tooltip>
)
Example #18
Source File: index.tsx    From ant-design-pro-V5-multitab with MIT License 5 votes vote down vote up
GlobalHeaderRight: React.FC = () => {
  const { initialState } = useModel('@@initialState');

  if (!initialState || !initialState.settings) {
    return null;
  }

  const { navTheme, layout } = initialState.settings;
  let className = styles.right;

  if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
    className = `${styles.right}  ${styles.dark}`;
  }
  return (
    <Space className={className}>
      <HeaderSearch
        className={`${styles.action} ${styles.search}`}
        placeholder="站内搜索"
        defaultValue="umi ui"
        options={[
          { label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
          {
            label: <a href="next.ant.design">Ant Design</a>,
            value: 'Ant Design',
          },
          {
            label: <a href="https://protable.ant.design/">Pro Table</a>,
            value: 'Pro Table',
          },
          {
            label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
            value: 'Pro Layout',
          },
        ]}
        // onSearch={value => {
        //   console.log('input', value);
        // }}
      />
      <HeaderDropdown
        overlay={
          <Menu>
            <Menu.Item
              onClick={() => {
                window.open('/~docs');
              }}
            >
              组件文档
            </Menu.Item>
            <Menu.Item
              onClick={() => {
                window.open('https://pro.ant.design/docs/getting-started');
              }}
            >
              Ant Design Pro 文档
            </Menu.Item>
          </Menu>
        }
      >
        <span className={styles.action}>
          <QuestionCircleOutlined />
        </span>
      </HeaderDropdown>
      <Avatar />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
      <SelectLang className={styles.action} />
    </Space>
  );
}
Example #19
Source File: index.tsx    From anew-server with MIT License 5 votes vote down vote up
GlobalHeaderRight: React.FC = () => {
  const { initialState } = useModel('@@initialState');

  if (!initialState || !initialState.settings) {
    return null;
  }

  const { navTheme, layout } = initialState.settings;
  let className = styles.right;

  if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
    className = `${styles.right}  ${styles.dark}`;
  }

  return (
    <Space className={className}>
      <HeaderSearch
        className={`${styles.action} ${styles.search}`}
        placeholder="站内搜索"
        defaultValue="umi ui"
        options={[
          {
            label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>,
            value: 'umi ui',
          },
          {
            label: <a href="next.ant.design">Ant Design</a>,
            value: 'Ant Design',
          },
          {
            label: <a href="https://protable.ant.design/">Pro Table</a>,
            value: 'Pro Table',
          },
          {
            label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
            value: 'Pro Layout',
          },
        ]} // onSearch={value => {
        //   console.log('input', value);
        // }}
      />
      <span
        className={styles.action}
        onClick={() => {
          window.open('https://pro.ant.design/docs/getting-started');
        }}
      >
        <QuestionCircleOutlined />
      </span>
      {/* <NoticeIconView /> */}
      <Avatar menu />
    </Space>
  );
}
Example #20
Source File: RightContent.tsx    From ui-visualization with MIT License 5 votes vote down vote up
GlobalHeaderRight: React.SFC<GlobalHeaderRightProps> = (props) => {
  const { theme, layout } = props;
  let className = styles.right;

  if (theme === 'dark' && layout === 'topmenu') {
    className = `${styles.right}  ${styles.dark}`;
  }

  return (
    <div className={className}>
      <HeaderSearch
        className={`${styles.action} ${styles.search}`}
        placeholder="站内搜索"
        defaultValue="umi ui"
        options={[
          { label: <a href="https://umijs.org/zh/guide/umi-ui.html">umi ui</a>, value: 'umi ui' },
          {
            label: <a href="next.ant.design">Ant Design</a>,
            value: 'Ant Design',
          },
          {
            label: <a href="https://protable.ant.design/">Pro Table</a>,
            value: 'Pro Table',
          },
          {
            label: <a href="https://prolayout.ant.design/">Pro Layout</a>,
            value: 'Pro Layout',
          },
        ]}
        // onSearch={value => {
        //   //console.log('input', value);
        // }}
      />
      <Tooltip title="使用文档">
        <a
          target="_blank"
          href="https://pro.ant.design/docs/getting-started"
          rel="noopener noreferrer"
          className={styles.action}
        >
          <QuestionCircleOutlined />
        </a>
      </Tooltip>
      <Avatar />
      {REACT_APP_ENV && (
        <span>
          <Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
        </span>
      )}
      <SelectLang className={styles.action} />
    </div>
  );
}
Example #21
Source File: textUtils.tsx    From jetlinks-ui-antd with MIT License 5 votes vote down vote up
createRichTextUtils = () => {
    return {
        text(...args: any[]) {
            return React.createElement('span', {}, ...args)
        },
        link(text: React.ReactNode, href: any, target: any) {
            return React.createElement('a', { href, target }, text)
        },
        gray(text: React.ReactNode) {
            return React.createElement(
                'span',
                { style: { color: 'gray', margin: '0 3px' } },
                text
            )
        },
        red(text: React.ReactNode) {
            return React.createElement(
                'span',
                { style: { color: 'red', margin: '0 3px' } },
                text
            )
        },
        help(text: any, offset = 3) {
            return React.createElement(
                Tooltip,
                { title: text },
                <QuestionCircleOutlined
                    style={{ margin: '0 3px', cursor: 'default', marginLeft: offset }}
                />
            )
        },
        tips(text: React.ReactNode, tips: any) {
            return React.createElement(
                Tooltip,
                { title: tips },
                <span style={{ margin: '0 3px', cursor: 'default' }}>{text}</span>
            )
        }
    }
}
Example #22
Source File: PluginList.tsx    From yakit with GNU Affero General Public License v3.0 5 votes vote down vote up
YakScriptCheckbox: React.FC<YakScriptCheckboxProp> = React.memo((props) => {
    const {info, selected, vlistWidth, selectScript, unSelectScript,} = props;

    return <div key={info.ScriptName} className='list-opt'>
        {props.readOnly ? <OneLine width={vlistWidth} overflow={"hidden"}>
            <div>
                {info.ScriptName}
            </div>
        </OneLine> : <Checkbox
            disabled={props.disabled}
            checked={selected.includes(info.ScriptName)}
            onChange={(r) => {
                if (r.target.checked) selectScript(info)
                else unSelectScript(info)
            }}
        >
            <OneLine width={vlistWidth} overflow={"hidden"}>
                <div>
                    {info.ScriptName}
                </div>
            </OneLine>
        </Checkbox>}
        <div style={{flex: 1, textAlign: "right"}}>
            {info.Help && (
                <a
                    onClick={() => {
                        showModal({
                            width: "40%",
                            title: "Help",
                            content: <>{info.Help}</>
                        })
                    }}
                    href={"#"} style={{marginLeft: 2, marginRight: 2}}
                ><QuestionCircleOutlined/></a>
            )}
            {info.Author && (
                <Tooltip title={info.Author}>
                    <a href={"#"} style={{marginRight: 2, marginLeft: 2}}><UserOutlined/></a>
                </Tooltip>
            )}
            {!!info.Content && props.readOnly && (
                <a href={"#"}
                   style={{marginRight: 2, marginLeft: 2}}
                   onClick={() => {
                       showModal({
                           title: info.ScriptName, width: "60%",
                           content: (
                               <div style={{height: 400}}>
                                   <YakEditor
                                       type={info.Type === "nuclei" ? "yaml" : "yak"}
                                       readOnly={true}
                                       value={info.Content}
                                   />
                               </div>
                           )
                       })
                   }}
                ><CodeOutlined/></a>
            )}
        </div>
    </div>
})
Example #23
Source File: yakitPlugin.tsx    From yakit with GNU Affero General Public License v3.0 5 votes vote down vote up
PluginListOptInfo: React.FC<PluginListOptInfoProps> = React.memo((props) => {
    const {info, selected, onSelect, disabled = false} = props

    return (
        <div className='plugin-list-opt-info-body'>
            <div className="plugin-list-opt-info-checkbox">
                <Checkbox
                    className='opt-info-checkbox'
                    checked={selected}
                    disabled={disabled}
                    onChange={(e) => onSelect(e.target.checked)}
                >
                    <div className='opt-info-checkbox-title' title={info.ScriptName}>
                        {info.ScriptName}
                    </div>
                </Checkbox>
            </div>
            <div className='plugin-list-opt-info-hint'>
                {info.Help && (
                    <a
                        onClick={() => {
                            showModal({
                                width: "40%",
                                title: "Help",
                                content: <>{info.Help}</>
                            })
                        }}
                        href={"#"}
                        className='opt-info-hint-a'
                    >
                        <QuestionCircleOutlined />
                    </a>
                )}
                {info.Author && (
                    <Tooltip title={info.Author}>
                        <a href={"#"} className='opt-info-hint-a'>
                            <UserOutlined />
                        </a>
                    </Tooltip>
                )}
            </div>
        </div>
    )
})
Example #24
Source File: index.tsx    From XFlow with MIT License 5 votes vote down vote up
/** icon map */
  private map = new Map<string, IconComponent>([
    ['default', QuestionCircleOutlined],
    ['QuestionCircleOutlined', QuestionCircleOutlined],
  ])
Example #25
Source File: index.tsx    From XFlow with MIT License 5 votes vote down vote up
constructor() {
    this.map.set('default', QuestionCircleOutlined)
    this.map.set('QuestionCircleOutlined', QuestionCircleOutlined)
  }
Example #26
Source File: EditItem.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
export default function EditItem(props: Props) {
  const { visible, onChange, value, range, id } = props;
  const { t } = useTranslation();
  const [form] = Form.useForm();
  useEffect(() => {
    value && form.setFieldsValue(value);
  }, [value]);
  const handleOk = async () => {
    await form.validateFields();
    const v: FormType = form.getFieldsValue();
    onChange(v);
  };
  const onCancel = () => {
    onChange(undefined);
  };

  const onFinish = (values) => {
    console.log('Received values of form:', values);
  };

  const handleBlur = (index) => {
    const reg = form.getFieldValue(['var', index, 'reg']);
    const expression = form.getFieldValue(['var', index, 'definition']);
    if ((!reg || new RegExp('^/(.*?)/(g?i?m?y?)$').test(reg)) && expression) {
      const formData = form.getFieldsValue();
      var newExpression = replaceExpressionVars(expression, formData, index, id);
      convertExpressionToQuery(newExpression, range).then((res) => {
        const regFilterRes = res.filter((i) => !reg || !stringToRegex(reg) || (stringToRegex(reg) as RegExp).test(i));
        if (regFilterRes.length > 0) {
          setVaraiableSelected(formData.var[index].name, regFilterRes[0], id);
        }
        // form.setFields([{ name: ['var', index, 'selected'], value: regFilterRes[0] }]);
      });
    }
  };

  return (
    <Modal title={t('大盘变量')} width={950} visible={visible} onOk={handleOk} onCancel={onCancel} wrapClassName='variable-modal'>
      <Form name='dynamic_form_nest_item' onFinish={onFinish} autoComplete='off' preserve={false} form={form}>
        <Row gutter={[6, 6]} className='tag-header'>
          <Col span={4}>{t('变量名')}</Col>
          <Col span={6}>
            {t('变量定义')}
            <QuestionCircleOutlined
              style={{ marginLeft: 5 }}
              onClick={() => window.open('https://grafana.com/docs/grafana/latest/datasources/prometheus/#query-variable', '_blank')}
            />
          </Col>
          <Col span={6}>{t('筛值正则')}</Col>
          <Col span={2}>{t('Multi')}</Col>
          <Col span={2}>{t('All Option')}</Col>
          <Col span={4}>{t('操作')}</Col>
        </Row>
        <Form.List name='var'>
          {(fields, { add, remove, move }) => (
            <>
              {fields.map(({ key, name, fieldKey, ...restField }) => (
                <Row gutter={[6, 6]} className='tag-content-item' key={key}>
                  <Col span={4}>
                    <Form.Item
                      {...restField}
                      name={[name, 'name']}
                      fieldKey={[fieldKey, 'name']}
                      rules={[
                        { required: true, message: t('请输入变量名') },
                        { pattern: /^[0-9a-zA-Z_]+$/, message: t('仅支持数字和字符下划线') },
                      ]}
                    >
                      <Input />
                    </Form.Item>
                  </Col>
                  <Col span={6}>
                    <Form.Item
                      {...restField}
                      name={[name, 'definition']}
                      fieldKey={[fieldKey, 'definition']}
                      rules={[
                        { required: true, message: t('请输入变量定义') },
                        {
                          validator(_, value) {
                            if (/^\s*label_values.+,\s*\$.+/.test(value)) {
                              return Promise.reject(new Error('label_values表达式的label不允许使用变量'));
                            }
                            return Promise.resolve();
                          },
                        },
                      ]}
                    >
                      <Input onBlur={(v) => handleBlur(name)} />
                    </Form.Item>
                  </Col>
                  <Col span={6}>
                    <Form.Item {...restField} name={[name, 'reg']} fieldKey={[fieldKey, 'reg']} rules={[{ pattern: new RegExp('^/(.*?)/(g?i?m?y?)$'), message: t('格式不对') }]}>
                      <Input placeholder='/*.hna/' onBlur={(v) => handleBlur(name)} />
                    </Form.Item>
                  </Col>
                  <Col span={2}>
                    <Form.Item {...restField} name={[name, 'multi']} fieldKey={[fieldKey, 'multi']} valuePropName='checked'>
                      <Switch />
                    </Form.Item>
                  </Col>
                  <Col span={2}>
                    <Form.Item shouldUpdate style={{ margin: 0 }}>
                      {() => {
                        return (
                          form.getFieldValue(['var', name, 'multi']) && (
                            <Form.Item {...restField} name={[name, 'allOption']} fieldKey={[fieldKey, 'allOption']} valuePropName='checked'>
                              <Switch />
                            </Form.Item>
                          )
                        );
                      }}
                    </Form.Item>
                  </Col>
                  {/* <Form.Item {...restField} name={[name, 'selected']} fieldKey={[fieldKey, 'selected']} hidden>
                    <Input />
                  </Form.Item> */}
                  <Col span={4}>
                    <Button type='link' size='small' onClick={() => move(name, name + 1)} disabled={name === fields.length - 1}>
                      <ArrowDownOutlined />
                    </Button>
                    <Button type='link' size='small' onClick={() => move(name, name - 1)} disabled={name === 0}>
                      <ArrowUpOutlined />
                    </Button>
                    <Button
                      type='link'
                      size='small'
                      onClick={() => {
                        const v = form.getFieldValue(['var', name]);
                        add({ ...v, name: 'copy_of_' + v.name });
                      }}
                    >
                      <CopyOutlined />
                    </Button>
                    <Button type='link' size='small' onClick={() => remove(name)}>
                      <DeleteOutlined />
                    </Button>
                  </Col>
                </Row>
              ))}
              <Form.Item>
                <Button type='dashed' onClick={() => add()} block icon={<PlusOutlined />}>
                  {t('新增变量')}
                </Button>
              </Form.Item>
            </>
          )}
        </Form.List>
      </Form>
    </Modal>
  );
}
Example #27
Source File: core.tsx    From amiya with MIT License 4 votes vote down vote up
install = (renderMap: AnyKeyProps) => {
  /**
   * 转化获得 field
   * @param field table Field
   * @param params 查询参数
   * @param tableData 表格数据
   * @param setTableData 设置表格数据
   * @param props 表格属性
   */
  const getAyTableField = (
    field: AnyKeyProps,
    params: AnyKeyProps,
    tableData: Array<AnyKeyProps>,
    setTableData: Dispatch<SetStateAction<Array<AnyKeyProps>>>,
    props?: AnyKeyProps
  ) => {
    // 支持 tooltip 属性
    let title = field.__alias || field.title
    if (field.tooltip) {
      title = (
        <span>
          {title}
          <Tooltip placement="top" title={field.tooltip}>
            <QuestionCircleOutlined style={{ marginLeft: 4 }} />
          </Tooltip>
        </span>
      )
    }

    let tableField: AnyKeyProps = {
      key: field.key,
      dataIndex: field.key,
      ...field,
      title
    }
    if (field.render) {
      tableField.render = field.render
    }

    if (Array.isArray(field.children)) {
      field.children = field.children.map(field => {
        return getAyTableField(field, params, tableData, setTableData)
      })
    }

    // options 自动注册
    if (field.options && !field.render && !tableField.renderType) {
      tableField.renderType = '__options'
    }

    // 处理筛选
    if (field.filter && field.options) {
      tableField.filters = field.filters || JSON.parse(JSON.stringify(field.options).replace(/"label"/g, '"text"'))
      tableField.filteredValue = params.filters[field.key]
      field.filterMultiple = field.filterMultiple || false
    }

    // 处理排序
    if (field.sort) {
      let sorts = params.sorts
      // 寻找在 params 存在的排序
      let sortItem = sorts.find((item: AnyKeyProps) => item.key === field.key)
      if (!sortItem) {
        // 不存在直接清空
        tableField.sortOrder = false
      } else {
        // 存在排序,则值为设置后的排序
        tableField.sortOrder = sortItem.order
      }
      tableField.sorter = field.sorter || { multiple: field.sortOrder }
    }

    // 多余显示 ...
    if (field.ellipsis) {
      tableField.ellipsis = {
        showTitle: false
      }
      tableField.renderType = '__ellipsis'
    }

    // 处理可编辑行
    if (field.editable) {
      tableField.renderType = field.renderType ? field.renderType : 'editable-cell-input'
      tableField.onCell = (record: AnyKeyProps) => {
        // 多行编辑下,优先执行配置上的属性
        let fieldCellProps = {}
        if (field.onCell) {
          fieldCellProps = field?.onCell(record)
        }
        return {
          ...fieldCellProps,
          record,
          field: field,
          tableData,
          setTableData,
          tableProps: props
        }
      }
    }

    if (
      !tableField.render &&
      renderMap[tableField.renderType] &&
      typeof renderMap[tableField.renderType] === 'function'
    ) {
      tableField.render = (text: ReactNode, record: AnyKeyProps, index: number) => {
        return renderMap[tableField.renderType]({ text, record, index, field: tableField })
      }
    }
    return tableField
  }

  /**
   * 重新过滤配置项
   * @param fields 配置项目
   * @param params 查询参数
   * @param tableData 表格数据
   * @param setTableData 设置表格数据
   * @param ctrl 操作列
   * @param props 表格属性
   */
  const getAyTableFields = (
    fields: Array<any>,
    params: AnyKeyProps,
    tableData: Array<AnyKeyProps>,
    setTableData: Dispatch<SetStateAction<Array<AnyKeyProps>>>,
    ctrl?: AyTableField,
    props?: AnyKeyProps
  ): Array<AyTableField> => {
    let tableFields = fields
      .filter(field => {
        if (field.__extraTouched) {
          return field.__hidden === false
        }
        if (typeof field.hidden === 'function') {
          return field.hidden()
        }
        return field.hidden !== true
      })
      .map(field => {
        return getAyTableField(field, params, tableData, setTableData, props)
      })

    // 保证操作列在最后
    if (ctrl && ctrl.render && tableFields.every(field => field.key !== TABLE_CTRL_KEY)) {
      ctrl.key = TABLE_CTRL_KEY
      ctrl.title = ctrl.title || '操作'
      ctrl.order = 999
      ctrl.__order = 999
      tableFields.push(ctrl)
    }
    // 排序
    tableFields = tableFields.sort((a: AyTableField, b: AyTableField) => {
      return a.order - b.order
    })

    // 二次排序
    if (tableFields.some(field => field.__extraTouched)) {
      tableFields = tableFields.sort((a: AyTableField, b: AyTableField) => {
        return (a.__order || 0) - (b?.__order || 0)
      })
    }

    return tableFields
  }

  return {
    getAyTableField,
    getAyTableFields
  }
}
Example #28
Source File: HackerPlugin.tsx    From yakit with GNU Affero General Public License v3.0 4 votes vote down vote up
HackerPlugin: React.FC<HackerPluginProps> = React.memo((props) => {
    const [token, setToken] = useState<string>(randomString(40))
    const [loading, setLoading] = useState<boolean>(false)
    const [lists, setLists, getLists] = useGetState<YakScript[]>([])
    const [keyword, setKeyword] = useState<string>("")
    const [limit, setLimit] = useState<number>(100)
    const [total, setTotal] = useState<number>(0)

    const [selected, setSelected] = useState<string[]>([])
    const [indeterminate, setIndeterminate] = useState<boolean>(false)
    const [checked, setChecked] = useState<boolean>(false)

    const containerRef = useRef()
    const wrapperRef = useRef()
    const [list] = useVirtualList(getLists(), {
        containerTarget: containerRef,
        wrapperTarget: wrapperRef,
        itemHeight: 40,
        overscan: 20
    })
    const [vlistHeigth, setVListHeight] = useState(600)

    const [execting, setExecting] = useState<boolean>(false)
    const [infoState, {reset, setXtermRef}, xtermRef] = useHoldingIPCRStream(
        `execute-packet-yak-script`,
        "ExecutePacketYakScript",
        token,
        () => setExecting(false)
    )

    const search = useMemoizedFn(() => {
        setLoading(true)
        queryYakScriptList(
            "packet-hack",
            (data, total) => {
                setTotal(total || 0)
                setLists(data)
            },
            () => setTimeout(() => setLoading(false), 300),
            limit,
            undefined,
            keyword
        )
    })

    const selectYakScript = useMemoizedFn((info: YakScript) => {
        setSelected([info.ScriptName])
        // if (!selected.includes(info.ScriptName)) {
        //     setSelected([...selected, info.ScriptName])
        // }
    })
    const unselectYakScript = useMemoizedFn((info: YakScript) => {
        setSelected([])
        // setSelected(selected.filter((i) => i !== info.ScriptName))
    })

    // useEffect(() => {
    //     const totalYakScript = lists.length
    //     const filterArr = lists.filter((item) => selected.indexOf(item.ScriptName) > -1)

    //     const IndeterminateFlag =
    //         (filterArr.length > 0 && filterArr.length < totalYakScript && selected.length !== 0) ||
    //         (filterArr.length === 0 && selected.length !== 0)
    //     const checkedFlag = filterArr.length === totalYakScript && selected.length !== 0

    //     setIndeterminate(IndeterminateFlag)
    //     setChecked(checkedFlag)
    // }, [selected, lists])

    const startScript = useMemoizedFn(() => {
        if (selected.length === 0) {
            failed("请选一个插件后在点击执行")
            return
        }
        setExecting(true)

        const params: ExecutePacketYakScriptProp = {
            ScriptName: selected[0],
            IsHttps: props.isHTTPS,
            Request: props.request
        }
        if (!!props.response) params.Response = props.response
        ipcRenderer
            .invoke("ExecutePacketYakScript", params, token)
            .then(() => {})
            .catch((e) => {
                failed(`Start Packet Checker Error: ${e}`)
                setExecting(false)
            })
    })
    const cancelScript = useMemoizedFn(() => {
        ipcRenderer.invoke("cancel-ExecutePacketYakScript", token)
    })

    useEffect(() => {
        search()
    }, [])

    const renderListItem = useMemoizedFn((info: YakScript) => {
        return (
            <div key={info.ScriptName} className='list-opt'>
                <Checkbox
                    checked={selected.includes(info.ScriptName)}
                    onChange={(r) => {
                        if (r.target.checked) selectYakScript(info)
                        else unselectYakScript(info)
                    }}
                >
                    <Space>
                        <Text style={{maxWidth: 270}} ellipsis={{tooltip: true}}>
                            {info.ScriptName}
                        </Text>
                        {info.Help && (
                            <Button
                                size={"small"}
                                type={"link"}
                                onClick={() => {
                                    showModal({
                                        width: "40%",
                                        title: "Help",
                                        content: <>{info.Help}</>
                                    })
                                }}
                                icon={<QuestionCircleOutlined />}
                            />
                        )}
                    </Space>
                </Checkbox>
                <div style={{flex: 1, textAlign: "right"}}>
                    {info.Author && (
                        <Tooltip title={info.Author}>
                            <Button size={"small"} type={"link"} icon={<UserOutlined />} />
                        </Tooltip>
                    )}
                </div>
            </div>
        )
    })

    return (
        <div className='mitm-exec-plugin'>
            <div className='left-body'>
                <AutoCard
                    size='small'
                    bordered={false}
                    title={"数据包扫描插件(暂只支持单选)"}
                    bodyStyle={{padding: "0 4px", overflowY: "hidden"}}
                    extra={
                        <Space>
                            {/* <Checkbox
                                indeterminate={indeterminate}
                                onChange={(r) => {
                                    if (r.target.checked) {
                                        const newSelected = [...lists.map((i) => i.ScriptName), ...selected]
                                        setSelected(newSelected.filter((e, index) => newSelected.indexOf(e) === index))
                                    } else {
                                        setSelected([])
                                    }
                                }}
                                checked={checked}
                            >
                                全选
                            </Checkbox> */}
                            <Popover
                                title={"额外设置"}
                                trigger={["click"]}
                                content={
                                    <div>
                                        <Form
                                            size={"small"}
                                            onSubmitCapture={(e) => {
                                                e.preventDefault()
                                                search()
                                            }}
                                        >
                                            <InputInteger
                                                label={"插件展示数量"}
                                                value={limit}
                                                setValue={setLimit}
                                                formItemStyle={{marginBottom: 4}}
                                            />
                                            <Form.Item colon={false} label={""} style={{marginBottom: 10}}>
                                                <Button type='primary' htmlType='submit'>
                                                    刷新
                                                </Button>
                                            </Form.Item>
                                        </Form>
                                    </div>
                                }
                            >
                                <Button size={"small"} icon={<SettingOutlined />} type={"link"} />
                            </Popover>
                            <Popover
                                title={"搜索插件关键字"}
                                trigger={["click"]}
                                content={
                                    <div>
                                        <Form
                                            size={"small"}
                                            onSubmitCapture={(e) => {
                                                e.preventDefault()
                                                search()
                                            }}
                                        >
                                            <InputItem
                                                label={""}
                                                extraFormItemProps={{style: {marginBottom: 4}, colon: false}}
                                                value={keyword}
                                                setValue={setKeyword}
                                            />
                                            <Form.Item colon={false} label={""} style={{marginBottom: 10}}>
                                                <Button type='primary' htmlType='submit'>
                                                    搜索
                                                </Button>
                                            </Form.Item>
                                        </Form>
                                    </div>
                                }
                            >
                                <Button
                                    size={"small"}
                                    type={!!keyword ? "primary" : "link"}
                                    icon={<SearchOutlined />}
                                />
                            </Popover>
                            {execting ? (
                                <Button
                                    type='link'
                                    danger
                                    style={{padding: "4px 0"}}
                                    icon={<PoweroffOutlined />}
                                    onClick={cancelScript}
                                />
                            ) : (
                                <Button
                                    type='link'
                                    style={{padding: "4px 0"}}
                                    icon={<CaretRightOutlined />}
                                    onClick={() => {
                                        xtermClear(xtermRef)
                                        reset()
                                        startScript()
                                    }}
                                />
                            )}
                        </Space>
                    }
                >
                    <div style={{height: "100%"}}>
                        <ReactResizeDetector
                            onResize={(width, height) => {
                                if (!width || !height) {
                                    return
                                }
                                setVListHeight(height)
                            }}
                            handleWidth={true}
                            handleHeight={true}
                            refreshMode={"debounce"}
                            refreshRate={50}
                        />
                        <div ref={containerRef as any} style={{height: vlistHeigth, overflow: "auto"}}>
                            <div ref={wrapperRef as any}>{list.map((i) => renderListItem(i.data))}</div>
                        </div>
                    </div>
                </AutoCard>
            </div>

            <div className='right-body'>
                <AutoCard
                    size='small'
                    bordered={false}
                    title={
                        <Space>
                            {"已选插件 / 当页插件 / 插件总量"}
                            <Tag>{`${selected.length} / ${lists.length} / ${total}`}</Tag>
                        </Space>
                    }
                    bodyStyle={{padding: 0, paddingLeft: 5}}
                >
                    <PluginResultUI
                        results={infoState.messageState}
                        progress={infoState.processState}
                        featureType={infoState.featureTypeState}
                        feature={infoState.featureMessageState}
                        statusCards={infoState.statusState}
                        loading={loading}
                        onXtermRef={setXtermRef}
                    />
                </AutoCard>
            </div>
        </div>
    )
})
Example #29
Source File: index.tsx    From amiya with MIT License 4 votes vote down vote up
getFormItem = (
  fields: Array<AyFormField | AySearchTableField>,
  formInstans: AnyKeyProps,
  props: AyFormProps,
  childrenType?: 'group' | 'card' | 'input-group' | 'list'
) => {
  const { span, readonly, formLayout, gutter } = props
  const ayFormProps: AyFormProps = props

  return fields.map((field: AyFormField | AySearchTableField, index: number) => {
    // 把其它属性 添加到 props 里面
    field = {
      ...field,
      props: {
        ...omitObj(field, fieldKeys),
        ...field.props
      }
    }

    const fieldSpan = field.span !== 0 ? field.span || span || 24 : span || 24

    if (field.type === FORM_TYPE_CARD) {
      let children = field.children || []
      if (!Array.isArray(children)) {
        children = [children]
      }
      let content = getFormItem(
        children as Array<AyFormField | AySearchTableField>,
        formInstans,
        ayFormProps,
        FORM_TYPE_CARD
      )
      return (
        <Col key={field.key} span={field.span || 24}>
          <AyCard title={field.title} {...field.props}>
            <Row gutter={gutter}>{content}</Row>
          </AyCard>
        </Col>
      )
    }
    if (childrenType === FORM_TYPE_LIST) {
      // debugger
    }

    let visible = true

    // 隐藏该项目,保留占位,但是保留值
    if (field.visible !== undefined) {
      visible = typeof field.visible === 'function' ? field.visible() : field.visible
    }

    let hidden = false

    // 隐藏该项目,不保留占位,但是保留值
    if (field.hidden !== undefined) {
      hidden = typeof field.hidden === 'function' ? field.hidden() : field.hidden
    }

    // 隐藏该项,只显示占位,保留 form 值
    if (!visible || hidden) {
      field = getNoVisibleField(field)
    }

    // 设置 Form.Item 的属性
    let formItemProps: AnyKeyProps = {
      ...field.formItemProps,
      label: field.title,
      name: field.key,
      extra: field.help
    }

    // 如果自元素类型是列表,则重置 name,此时一定有 field.formItemProps
    if (childrenType === FORM_TYPE_LIST) {
      formItemProps.name = field.formItemProps.name
    }

    // 组合元素的 formItem 不需要样式
    if (childrenType === FORM_TYPE_GROUP || childrenType === FORM_TYPE_INPUT_GROUP) {
      formItemProps.noStyle = true
    }

    // 设定 开关、多选框 等的值类型 (这是 ant design form 的限制)
    if (field.type && fieldMap[field.type]) {
      formItemProps.valuePropName = fieldMap[field.type].valuePropName || 'value'
    }

    // 设置每个【表单项】的占位
    const colProps: ColProps = {
      span: fieldSpan,
      offset: field.offset
    }

    // 填充 rules 属性
    if (field.rules) {
      formItemProps.rules = [...field.rules]
    }

    // 填充快捷 required 属性
    if (field.required) {
      let rule = { required: true, message: getPlaceholder(field) + locale.form.requiredText }
      if (field.children && field.type !== FORM_TYPE_CHECKBOX) {
        formItemProps.label = (
          <span>
            <span className="required-mark">*</span>
            {field.title}
          </span>
        )
      } else {
        if (formItemProps.rules) {
          formItemProps.rules.push(rule)
        } else {
          formItemProps.rules = [rule]
        }
      }
    }

    // 不保留占位
    if (hidden) {
      colProps.span = 0
      colProps.xs = 0
      colProps.sm = 0
      colProps.md = 0
      colProps.lg = 0
      colProps.xl = 0
    }

    // 不显示状态下 rule 无效
    if (hidden || !visible) {
      formItemProps.rules = []
    }

    // 支持 tooltip 属性
    if (field.tooltip) {
      formItemProps.label = (
        <span>
          {field.title}
          <Tooltip placement="top" title={field.tooltip}>
            <QuestionCircleOutlined style={{ marginLeft: 4 }} />
          </Tooltip>
        </span>
      )
    }

    let tag: ReactNode

    switch (field.type) {
      // 组合类型
      case FORM_TYPE_GROUP:
        tag = (
          <Row className="ay-form-group" {...field.props}>
            {getFormItem(
              field.children as Array<AyFormField | AySearchTableField>,
              formInstans,
              ayFormProps,
              FORM_TYPE_GROUP
            )}
          </Row>
        )
        break
      // 输入框组合
      case FORM_TYPE_INPUT_GROUP:
        tag = (
          <Input.Group compact {...field.props}>
            {getFormItem(
              field.children as Array<AyFormField | AySearchTableField>,
              formInstans,
              ayFormProps,
              FORM_TYPE_INPUT_GROUP
            )}
          </Input.Group>
        )
        break
      // 列表类型
      case FORM_TYPE_LIST:
        tag = (
          <AyFormList
            field={field as AyFormField}
            formInstant={formInstans}
            getFormItem={getFormItem}
            ayFormProps={ayFormProps}
          />
        )
        break

      default:
        tag = getTag(field, fields, formInstans, readonly)
        break
    }

    const content = field.render ? (
      field.render(field as AyFormField, formInstans.getFieldsValue() || getDefaultValue(fields), index)
    ) : (
      <Form.Item key={field.key} {...formItemProps}>
        {tag}
      </Form.Item>
    )

    if (formLayout === 'inline' || childrenType === FORM_TYPE_INPUT_GROUP) {
      return content
    }

    return (
      <Col key={field.key} {...colProps}>
        {content}
      </Col>
    )
  })
}