antd#Image TypeScript Examples

The following examples show how to use antd#Image. 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: TrackListHeader.tsx    From spotify-recently-played-readme with MIT License 6 votes vote down vote up
/**
 * Track list header component.
 */
export default function TrackListHeader(props: Props): JSX.Element {
    return (
        <div style={{ display: 'flex' }}>
            <Space>
                <a
                    target="_blank"
                    rel="noopener noreferrer"
                    href={`https://open.spotify.com/user/${props.username}`}
                    style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
                    <Image preview={false} className="spotify-icon" src={SpotifyIcon} width={100}></Image>
                </a>
                <Text className="spotify-title">Recently Played</Text>
            </Space>
        </div>
    );
}
Example #2
Source File: GeneralImage.spec.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
describe("GeneralImages", () => {
  it("should work", () => {
    const props = {
      src: "/images/1234.jpg",
      extra: {
        useBrick: {
          brick: "div",
          properties: {
            textContent: "1234.jpg",
          },
        },
      },
    };
    const wrapper = shallow<GeneralImageProps>(<GeneralImage {...props} />);
    const imageProps = wrapper.find(Image).props();
    expect(imageProps.src).toEqual("/images/1234.jpg");
    expect(imageProps.preview).toBeUndefined();

    const handleVisibleChange = jest.fn();
    wrapper.setProps({ visible: true, onVisibleChange: handleVisibleChange });
    const preview = wrapper.find(Image).prop("preview") as ImagePreviewType;
    expect(preview.visible).toBe(true);
    act(() => {
      preview.onVisibleChange(false, true);
    });
    expect(handleVisibleChange).toBeCalledWith(false, true);
  });
});
Example #3
Source File: GeneralImage.tsx    From next-basics with GNU General Public License v3.0 6 votes vote down vote up
export function GeneralImage(props: GeneralImageProps): React.ReactElement {
  const {
    width,
    height,
    src,
    alt,
    preview,
    visible,
    onVisibleChange,
    placeholder,
    fallback,
    extra,
    extraContainerStyle,
    dataSource,
  } = props;

  return (
    <div>
      <Image
        width={width}
        height={height}
        src={src}
        alt={alt}
        preview={!isNil(visible) ? { visible, onVisibleChange } : preview}
        placeholder={placeholder}
        fallback={fallback}
      />
      {extra && (
        <div className={style.extraContainer} style={extraContainerStyle}>
          <BrickAsComponent useBrick={extra.useBrick} data={dataSource} />
        </div>
      )}
    </div>
  );
}
Example #4
Source File: TopCard.tsx    From condo with MIT License 6 votes vote down vote up
TopCardTitle: React.FC<TopCardTitleProps> = ({ logoSrc, title, description }) => {
    const { width } = useWindowSize()
    const isSmallLayout = Boolean(width && width < TITLE_VERTICAL_MARK)

    const rowMargins: CSSProperties = isSmallLayout ? { marginTop: 180 } : { marginLeft: 200, marginTop: 12 }

    return (
        <>
            <LogoContainer centered={isSmallLayout}>
                <Image src={logoSrc || FALLBACK_IMAGE} style={IMAGE_STYLES} preview={false} fallback={FALLBACK_IMAGE}/>
            </LogoContainer>
            <Row gutter={[0, 16]} style={rowMargins}>
                <Col span={24}>
                    <Typography.Title level={4} style={WRAP_TEXT_STYLES}>
                        {title}
                    </Typography.Title>
                </Col>
                <Col span={24}>
                    <Typography.Paragraph style={WRAP_TEXT_STYLES} type={'secondary'}>
                        {description}
                    </Typography.Paragraph>
                </Col>
            </Row>
        </>
    )
}
Example #5
Source File: Logo.tsx    From condo with MIT License 6 votes vote down vote up
Logo: React.FC<ILogoProps> = (props) => {
    const {
        onClick,
        minified,
        fillColor = colors.logoPurple,
    } = props

    if (minified) {
        return (
            <LogoWrapper onClick={onClick}>
                <svg width="29" height="31" fill="none" xmlns="http://www.w3.org/2000/svg">
                    <path fill="#fff" d="M0 0h29v31H0z"/>
                    <path fillRule="evenodd" clipRule="evenodd" d="M12.5635 7.1615c-.7113-.572-1.7329-.5692-2.4409.0069L.7004 14.8348C.257 15.1957 0 15.7333 0 16.3006v12.7995c0 1.0492.8619 1.8998 1.925 1.8998h18.9622c1.0632 0 1.9251-.8506 1.9251-1.8998V16.3072c0-.571-.2603-1.1118-.7089-1.4726l-9.5399-7.673Zm6.3986 20.0389v-9.9907l-7.6078-6.1191-7.5041 6.1059v10.0039H18.962Z" fill="url(#a)"/>
                    <path d="M29 4.0124c0 2.216-1.8177 4.0124-4.0598 4.0124-2.2422 0-4.0598-1.7964-4.0598-4.0124S22.698 0 24.9402 0C27.1823 0 29 1.7964 29 4.0124Z" fill="#FDCF5A"/>
                    <defs>
                        <linearGradient id="a" x1="0" y1="18.8671" x2="18.2733" y2="27.9744" gradientUnits="userSpaceOnUse">
                            <stop stopColor="#4CD174"/><stop offset="1" stopColor="#6DB8F2"/>
                        </linearGradient>
                    </defs>
                </svg>
            </LogoWrapper>
        )
    }

    return (
        <LogoWrapper onClick={onClick}>
            <Image preview={false} css={SunCSS} src={'/logoSun.svg'}/>
            <Image preview={false} src={'/logoDoma.svg'}/>
        </LogoWrapper>
    )
}
Example #6
Source File: Comment.tsx    From condo with MIT License 6 votes vote down vote up
CommentFileList: React.FC<CommentFileListProps> = ({ comment }) => {
    const files = get(comment, 'files')
    const fileList = useMemo(() => files.map(({ id, file }, index) => {
        const fileNameArr = file.originalFilename.split('.')
        const fileExt = fileNameArr.pop()
        const fileName = fileNameArr.join('.')
        const mimetype = get(file, 'mimetype')
        const url = get(file, 'publicUrl')
        const TextWrapComponent = mimetype.startsWith('image') ? Typography.Paragraph : Typography.Link

        return (
            <TextWrapComponent
                href={url}
                key={index}
                style={TEXT_WRAP_COMPONENT_STYLES}
            >
                {getFilePreviewByMimetype(mimetype, url)}
                <Typography.Paragraph ellipsis={ELLIPSIS_CONFIG} style={FILENAME_TEXT_STYLES}>
                    {fileName}
                    <Typography.Text type={'secondary'}>
                        .{fileExt}
                    </Typography.Text>
                </Typography.Paragraph>
            </TextWrapComponent>
        )
    }), [files])

    if (isEmpty(files)) return null

    return (
        <Image.PreviewGroup>
            <CommentFileListWrapper>
                {fileList}
            </CommentFileListWrapper>
        </Image.PreviewGroup>
    )
}
Example #7
Source File: index.tsx    From metaplex with Apache License 2.0 6 votes vote down vote up
CachedImageContent = ({
  uri,
  className,
  preview,
  style,
}: {
  uri?: string;
  className?: string;
  preview?: boolean;
  style?: React.CSSProperties;
}) => {
  const { cachedBlob } = useCachedImage(uri || '');

  return (
    <Image
      fallback="image-placeholder.svg"
      src={cachedBlob}
      preview={preview}
      wrapperClassName={className}
      loading="lazy"
      wrapperStyle={{ ...style }}
      placeholder={<ThreeDots />}
    />
  );
}
Example #8
Source File: index.tsx    From metaplex with Apache License 2.0 6 votes vote down vote up
ReviewAndMintStep = ({
  uri,
  name,
  description,
  supplyByMetadataKey,
  allowedAmountToRedeem,
  distributionType,
}: ReviewAndMintStepProps): ReactElement => {
  const totalNFTs = getTotalNFTsCount(supplyByMetadataKey);
  const numberOfPacks = Math.floor(totalNFTs / allowedAmountToRedeem) || 0;
  const isUnlimited = distributionType === PackDistributionType.Unlimited;

  return (
    <div className="review-step-wrapper">
      <Image
        wrapperClassName="review-step-wrapper__image-wrapper"
        className="review-step-wrapper__image"
        src={uri}
        preview
        loading="lazy"
      />

      <p className="review-step-wrapper__title">{name}</p>

      <p className="review-step-wrapper__text">{description}</p>

      <p className="review-step-wrapper__subtitle">Number of packs</p>
      <p className="review-step-wrapper__text">
        {isUnlimited ? 'Unlimited' : numberOfPacks}
      </p>

      <p className="review-step-wrapper__subtitle">Total NFTs</p>
      <p className="review-step-wrapper__text">
        {isUnlimited ? 'Unlimited' : totalNFTs}
      </p>
    </div>
  );
}
Example #9
Source File: UserWelcomeTitle.tsx    From condo with MIT License 6 votes vote down vote up
WelcomeHeaderTitle: React.FC = () => {
    const intl = useIntl()
    const WelcomeTitleMessage = intl.formatMessage({ id: 'pages.auth.IAmResident' })

    return (
        <Row style={ROW_TITLE_STYLE} gutter={ITEMS_HEADER_GUTTER}>
            <Image
                preview={false}
                src={'/WomanHeaderWelcome.png'}
                css={WomanPictureCSS}
            />
            <Image
                preview={false}
                src={'/ManHeaderWelcome.png'}
                css={ManPictureCSS}
            />
            <Typography.Text
                onClick={() => Router.push(LANDING_PAGE_ADDRESS)}
                css={WelcomeTypographyCSS}
                underline
            >
                {WelcomeTitleMessage}
            </Typography.Text>
        </Row>
    )
}
Example #10
Source File: everyDay.tsx    From Search-Next with GNU General Public License v3.0 6 votes vote down vote up
EveryDay: React.FC<EveryDayProps> = ({ data }) => {
  const [url, setUrl] = React.useState<string>('');

  React.useEffect(() => {
    if (data && data?.url) {
      setUrl(data?.url);
    }
  }, [data]);

  return (
    <div>
      <Alert severity="info">每天更新背景,来源:必应壁纸</Alert>
      {url && (
        <div
          className={classNames(
            'm-2 rounded overflow-hidden',
            css`
              .ant-image {
                display: block;
              }
            `,
          )}
        >
          <Image src={url} />
        </div>
      )}
    </div>
  );
}
Example #11
Source File: AppSelectCard.tsx    From condo with MIT License 5 votes vote down vote up
AppSelectCard: React.FC<AppSelectCardProps> = ({ logoSrc, tag, disabled, url, title, description }) => {
    const intl = useIntl()
    const MoreMessage = intl.formatMessage({ id: 'miniapps.More' })

    const router = useRouter()

    const clickHandler = () => {
        if (disabled) return
        router.push(url)
    }

    return (
        <CardWrapper disabled={disabled}>
            <Card
                title={<Image src={logoSrc || FALLBACK_IMAGE} style={IMAGE_STYLES} preview={false} fallback={FALLBACK_IMAGE}/>}
                bordered={false}
                onClick={clickHandler}
            >
                <Row gutter={[0, 12]}>
                    <Col span={24}>
                        <Typography.Title level={5} ellipsis={true}>
                            {title}
                        </Typography.Title>
                    </Col>
                    <Col span={24}>
                        <Typography.Paragraph style={PARAGRAPH_STYLE} ellipsis={{ rows: 3 }}>
                            <Typography.Text type={'secondary'}>
                                {description}
                            </Typography.Text>
                        </Typography.Paragraph>
                    </Col>
                    <Col span={24}>
                        <Button
                            style={BUTTON_STYLES}
                            type={'sberBlack'}
                            disabled={disabled}
                        >
                            {MoreMessage}
                        </Button>
                    </Col>
                </Row>
            </Card>
            {
                tag && (
                    <TagContainer right={4} top={4}>
                        <Typography.Text type={'secondary'}>
                            {tag}
                        </Typography.Text>
                    </TagContainer>
                )
            }
        </CardWrapper>
    )
}
Example #12
Source File: AboutCard.tsx    From condo with MIT License 5 votes vote down vote up
AboutCard: React.FC<AboutCardProps> = ({ sections }) => {
    const intl = useIntl()
    const AboutServiceMessage = intl.formatMessage({ id: 'miniapps.AboutService' })

    const { width } = useWindowSize()
    const isSingleRow = Boolean(width && width < SINGLE_CARD_WIDTH_MARK)

    return (
        <CardWrapper>
            <Card bordered={false}>
                <Row gutter={[0, 40]}>
                    <Col span={24}>
                        <Typography.Title level={4}>
                            {AboutServiceMessage}
                        </Typography.Title>
                    </Col>
                    <Col span={24}>
                        <Row gutter={[40, 40]}>
                            {
                                sections.map((section, index) => {
                                    return (
                                        <Col span={isSingleRow ? 24 : 12} key={index}>
                                            <Card bordered={false} className={'about-block-card'}>
                                                <AboutImageWrapper>
                                                    <Image
                                                        src={section.imageSrc}
                                                        style={IMAGE_STYLE}
                                                        preview={false}
                                                        className={'about-block-image'}
                                                    />
                                                </AboutImageWrapper>
                                                <Row gutter={[0, 8]} style={TEXT_BLOCK_STYLE}>
                                                    <Col span={24}>
                                                        <Typography.Title level={5} ellipsis={true}>
                                                            {section.title}
                                                        </Typography.Title>
                                                    </Col>
                                                    <Col span={24}>
                                                        <Typography.Paragraph style={DESCRIPTION_TEXT_STYLE} type={'secondary'}>
                                                            {section.description}
                                                        </Typography.Paragraph>
                                                    </Col>
                                                </Row>
                                            </Card>
                                        </Col>
                                    )
                                })
                            }
                        </Row>
                    </Col>
                </Row>
            </Card>
        </CardWrapper>
    )
}
Example #13
Source File: WelcomePopup.tsx    From condo with MIT License 5 votes vote down vote up
export function WelcomePopup () {
    const intl = useIntl()

    const [step, setStep] = useState(0)
    const [visible, setVisible] = useState(true)

    const handleModalClose = useCallback(() => setVisible(false), [setVisible])

    const stepToContent: WelcomePopupStep[] = useMemo(() => ([
        {
            imageBackgroundColor: WELCOME_POPUP_BACKGROUND_COLORS.firstStep,
            images: [{ src: '/welcomePopupStep1.png', style: { maxHeight: '236px' } }],
        },
        {
            imageBackgroundColor: WELCOME_POPUP_BACKGROUND_COLORS.secondStep,
            images: [{ src: '/welcomePopupStep2_1.png', style: { maxHeight: '257px' } }, { src: '/welcomePopupStep2_2.png', style: { maxHeight: '202px', position: 'relative', bottom: '8px' } }],
        },
        {
            imageBackgroundColor: WELCOME_POPUP_BACKGROUND_COLORS.thirdStep,
            images: [{ src: '/welcomePopupStep3.png', style: { maxHeight: '202px' } }],
        },
    ]), [])

    const stepImages = useMemo(() => stepToContent[step].images.map(image => (
        <Col key={image.src}>
            <Image style={image.style} src={image.src} preview={false}/>
        </Col>
    )), [step, stepToContent])

    const backgroundImageStyles = useMemo(() => (
        { backgroundColor: stepToContent[step].imageBackgroundColor, height: '300px', display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: '12px' }
    ), [step, stepToContent])

    return (
        <Modal
            css={modalCss}
            centered
            visible={visible}
            closable={false}
            onCancel={handleModalClose}
            title={<ModalHeader handleModalClose={handleModalClose}/>}
            footer={<ModalFooter step={step} setStep={setStep} handleModalClose={handleModalClose}/>}
            width={570}
        >
            <Row gutter={[0, 24]}>
                <Col span={24} style={backgroundImageStyles}>
                    <Row gutter={[0, 20]}>
                        {stepImages}
                    </Row>
                </Col>
                <Col span={24}>
                    <Row gutter={[0, 12]}>
                        <Col>
                            <Typography.Title level={5}>
                                {intl.formatMessage({ id: `WelcomePopup.step${step + 1}.title` })}
                            </Typography.Title>
                        </Col>
                        <Col>
                            <Typography.Paragraph style={BODY_TEXT_STYLES}>
                                {intl.formatMessage({ id: `WelcomePopup.step${step + 1}.text` })}
                            </Typography.Paragraph>
                        </Col>
                    </Row>
                </Col>
            </Row>
        </Modal>
    )
}
Example #14
Source File: AuthHeader.tsx    From condo with MIT License 5 votes vote down vote up
AuthHeader: React.FC<IAuthHeaderProps> = ({ headerAction }) => {
    const { isSmall } = useLayoutContext()
    const router = useRouter()
    const { isAuthenticated } = useAuth()

    const handleLogoClick = useCallback(() => {
        if (isAuthenticated) {
            router.push('/')
        } else {
            router.push('/auth/signin')
        }
    }, [isAuthenticated, router])

    return (
        isSmall
            ? (
                <>
                    <MobileHeader>
                        <Row style={LOGO_HEADER_STYLES}>
                            <Col style={HEADER_LOGO_STYLE}>
                                <Logo fillColor={colors.backgroundLightGrey} onClick={handleLogoClick}/>
                            </Col>
                            <Col style={HEADER_ACTION_STYLES}>
                                <ActionContainer>{headerAction}</ActionContainer>
                            </Col>
                        </Row>
                        <Row justify={'center'}>
                            <Col style={MINI_POSTER_STYLES}>
                                <Image preview={false} src={'/miniPoster.png'}/>
                            </Col>
                        </Row>
                    </MobileHeader>
                </>
            )
            : (
                <Row>
                    <Header>
                        <Row style={LOGO_HEADER_STYLES}>
                            <Col style={HEADER_LOGO_STYLE}>
                                <Logo fillColor={colors.scampi} onClick={handleLogoClick}/>
                            </Col>
                            <Col style={HEADER_ACTION_STYLES}>
                                {headerAction}
                            </Col>
                        </Row>
                    </Header>
                </Row>
            )
    )
}
Example #15
Source File: index.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
ImageUploader: React.FC<ImageUploaderProps> = (props) => {
  const {value, onChange} = props;
  const [loading, setLoading] = useState<boolean>(false);
  return (
    <Upload
      accept={'.jpg,.png,.jpeg'}
      name='avatar'
      listType='picture-card'
      className={styles.imageUploader}
      showUploadList={false}
      beforeUpload={(file) => {
        if (!['image/jpeg', 'image/png', 'image/jpg'].includes(file.type)) {
          message.error('只能上传jpg和png格式');
          return false;
        }
        if (file.size / 1024 / 1024 > 20) {
          message.error('图片最大20M');
          return false;
        }
        return true;
      }}
      onChange={(info) => {
        if (info.file.status === 'uploading') {
          setLoading(true);
          return;
        }
        if (info.file.status === 'done') {
          setLoading(false);
        }
      }}
      {...(_.omit(props, ['value']))}
    >
      <div>
        {value && (
          <Badge
            count={
              <CloseCircleFilled
                onClick={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                  if (onChange) {
                    onChange('');
                  }
                  setLoading(false);
                }}
                style={{color: 'rgb(199,199,199)'}}
              />
            }
          >
            <Image
              preview={false}
              className={styles.image}
              src={value}
              fallback={defaultImage}
            />
          </Badge>
        )}
        {!value && (
          <div className={styles.button}>
            {loading ? <LoadingOutlined/> : <PlusCircleFilled/>}
            <div className={styles.text}>上传图片</div>
          </div>
        )}
      </div>
    </Upload>
  );
}
Example #16
Source File: index.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
fileMap = {
  'formImage': {
    accept: '.jpg,.png',
    contentType: ['image/png', 'image/jpg'],
    limitSize: 2,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    existValueRender: (value: any, fileInfo: any, fileType: string) => (
      <Image
        preview={false}
        className={styles.image}
        src={value}
        fallback={defaultImage}
      />
    ),
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    noValueRender: (loading: boolean, fileType: string) => (
      <div className={styles.formImageButton}>
        {loading ? <LoadingOutlined/> : <PlusCircleFilled/>}
        <div className={styles.text}>上传图片</div>
      </div>
    ),
  },
  '海报': {
    accept: '.jpg,.png',
    contentType: ['image/png', 'image/jpg'],
    limitSize: 2,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    existValueRender: (value: any, fileInfo: any, fileType: string) => (
      <Image
        preview={false}
        className={styles.image}
        src={value}
        fallback={defaultImage}
      />
    ),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType)
  },
  '视频': {
    accept: '.mp4',
    contentType: ['video/mp4'],
    limitSize: 10,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    existValueRender: (value: any, fileInfo: any, fileType: string) => (
      <video src={value} style={{width: 260}} controls={true}></video>
    ),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },
  'PDF': {
    accept: '.pdf',
    contentType: ['application/pdf'],
    limitSize: 20,
    image: pdfImage,
    existValueRender: (value: any, fileInfo: any, fileType: string) => commonExistValueRender(value, fileInfo, fileType),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },
  'PPT': {
    accept: '.pptx,.ppt',
    contentType: ['application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'],
    limitSize: 20,
    image: pptImage,
    existValueRender: (value: any, fileInfo: any, fileType: string) => commonExistValueRender(value, fileInfo, fileType),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },
  '表格': {
    accept: '.xls,.xlsx',
    contentType: ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
    limitSize: 20,
    image: excelImage,
    existValueRender: (value: any, fileInfo: any, fileType: string) => commonExistValueRender(value, fileInfo, fileType),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },
  '文档': {
    accept: '.doc,.docx',
    contentType: ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
    limitSize: 20,
    image: wordImage,
    existValueRender: (value: any, fileInfo: any, fileType: string) => commonExistValueRender(value, fileInfo, fileType),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  }
}
Example #17
Source File: ScriptContentPreView.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
ScriptContentPreView: React.FC<ScriptContentPreViewProps> = (props) => {
  const {script} = props
  return (
    <div>
      {
        script.reply_details.map((reply: any, index) => {
          if (index < 2) {
            return <div style={{width: 200}}>
              {
                reply.content_type === 2 && <div key={reply.id} style={{width: '100%', margin: '8px 0'}}>
                  <ExpandableParagraph content={reply.quick_reply_content?.text?.content} rows={4}/>
                </div>
              }
              {
                reply.content_type === 3 && <div key={reply.id} className={styles.imageOverview}>
                  <div className={styles.leftPart}>
                    <Image src={reply.quick_reply_content?.image?.picurl} width={iconWidth} fallback={damagedImage}/>
                  </div>
                  <div className={styles.rightPart}>
                    <p>{reply.quick_reply_content?.image?.title}</p>
                    <p>{parseFileSize(reply.quick_reply_content?.image?.size)}</p>
                  </div>
                </div>
              }
              {
                reply.content_type === 4 && <div className={styles.imageOverview}>
                  <div className={styles.leftPart}>
                    <Image src={reply.quick_reply_content?.link?.picurl} width={iconWidth} fallback={damagedImage}/>
                  </div>
                  <div className={styles.rightPart}>
                    <Tooltip placement="topLeft" title={reply.quick_reply_content?.link?.title}>
                      <p>{reply.quick_reply_content?.link?.title}</p>
                    </Tooltip>
                    <Tooltip placement="topLeft" title={reply.quick_reply_content?.link?.desc}>
                      <p>{reply.quick_reply_content?.link?.desc}</p>
                    </Tooltip>
                  </div>
                </div>
              }
              {
                reply.content_type === 5 && <div className={styles.imageOverview}>
                  <div className={styles.leftPart}>
                    <Image src={pdfImage} width={iconWidth} preview={false} fallback={damagedImage}/>
                  </div>
                  <div className={styles.rightPart}>
                    <p>{reply.quick_reply_content?.pdf?.title}</p>
                    <p>{parseFileSize(reply.quick_reply_content?.pdf?.size)}</p>
                  </div>
                </div>
              }
              {
                reply.content_type === 6 && <div className={styles.imageOverview}>
                  <div className={styles.leftPart}>
                    <Image src={videoImage} width={iconWidth} preview={false} fallback={damagedImage}/>
                  </div>
                  <div className={styles.rightPart}>
                    <p>{reply.quick_reply_content?.video?.title}</p>
                    <p>{parseFileSize(reply.quick_reply_content?.video?.size)}</p>
                  </div>
                </div>
              }
            </div>
          }
          if (index === 3) {
            return <div style={{color: '#666'}}>...</div>
          }
          return <></>
        })
      }
      <div style={{color: '#666'}}>共{script.reply_details.length}条</div>
    </div>
  )
}
Example #18
Source File: index.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
fileMap = {
  'formImage': {
    accept: '.jpg,.png',
    contentType: [ 'image/png', 'image/jpg'],
    limitSize: 2,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    existValueRender: (value: any, fileInfo: any, fileType: string) => (
      <Image
        preview={false}
        className={styles.image}
        src={value}
        fallback={defaultImage}
      />
    ),
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    noValueRender: (loading: boolean, fileType: string) => (
      <div className={styles.formImageButton}>
        {loading ? <LoadingOutlined/> : <PlusCircleFilled/>}
        <div className={styles.text}>上传图片</div>
      </div>
    ),
  },
  '视频': {
    accept: '.mp4',
    contentType: ['video/mp4'],
    limitSize: 10,
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    existValueRender: (value: any, fileInfo: any, fileType: string) => (
          <video src={value} style={{width: 260}} controls={true}></video>
    ),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },
  'PDF': {
    accept: '.pdf',
    contentType: ['application/pdf'],
    limitSize: 20,
    image: pdfImage,
    existValueRender: (value: any, fileInfo: any, fileType: string) => commonExistValueRender(value, fileInfo, fileType),
    noValueRender: (loading: boolean, fileType: string) => commonNoValueRender(loading, fileType),
  },

}
Example #19
Source File: image-renderer.tsx    From electron-playground with MIT License 5 votes vote down vote up
CodeRenderer: React.FunctionComponent<IMarkdownProps> = props => {
  const { src } = props
  const parseObj = queryString.parseUrl(src)
  return <Image src={src} {...parseObj.query} />
}
Example #20
Source File: UnusedResourceView.tsx    From joplin-utils with MIT License 5 votes vote down vote up
UnusedResourceView: React.FC = () => {
  const [list, setList] = useState<Pick<ResourceProperties, 'id' | 'title' | 'mime'>[]>([])
  const [loadingMsg, setLoadingMsg] = useState('')
  const [state, onCheck] = useAsyncFn(async () => {
    try {
      const list = await unusedResourceService.getUnusedResource().on('process', (info) => {
        setLoadingMsg(i18n.t('unusedResource.msg.process', info))
      })
      console.log('list: ', list)
      setList(list)
    } catch (e) {
      message.error(i18n.t('unusedResource.msg.error'))
    }
  })

  async function onRemoveResource(id: string) {
    setList(produce((list) => list.filter((item) => item.id !== id)))
    await joplinApiGenerator.resourceApi.remove(id)
  }

  async function onOpenResource(id: string) {
    await downloadUrl(buildResourceUrl(id))
  }

  const [onRemoveAllState, onRemoveAll] = useAsyncFn(async () => {
    await AsyncArray.forEach(list, async (item) => {
      await joplinApiGenerator.resourceApi.remove(item.id)
    })
    setList([])
  }, [list])

  return (
    <Card
      title={i18n.t('unusedResource.title')}
      extra={
        <Space>
          <Button onClick={onCheck}>{i18n.t('common.action.check')}</Button>
          <Button disabled={list.length === 0} danger={true} loading={onRemoveAllState.loading} onClick={onRemoveAll}>
            {i18n.t('unusedResource.action.removeAll')}
          </Button>
        </Space>
      }
    >
      <List
        dataSource={list}
        locale={{
          emptyText: i18n.t('unusedResource.listEmptyText'),
        }}
        renderItem={(item) => (
          <List.Item
            key={item.id}
            actions={[
              <Button onClick={() => onRemoveResource(item.id)}>{i18n.t('common.action.remove')}</Button>,
              <Button onClick={() => onOpenResource(item.id)}>{i18n.t('common.action.download')}</Button>,
            ]}
            extra={item.mime.startsWith('image/') && <Image src={buildResourceUrl(item.id)} width={300} />}
          >
            <List.Item.Meta title={item.title} />
          </List.Item>
        )}
        loading={
          {
            spinning: state.loading,
            tip: loadingMsg,
          } as SpinProps
        }
      />
    </Card>
  )
}
Example #21
Source File: AppCarouselCard.tsx    From condo with MIT License 5 votes vote down vote up
AppCarouselCard: React.FC<AppCarouselCardProps> = ({ logoSrc, title, url }) => {
    const intl = useIntl()
    const ConnectedLabel = intl.formatMessage({ id: 'Connected' })
    const router = useRouter()

    const handleCardClick = useCallback(() => {
        router.push(url)
    }, [router, url])

    return (
        <CardWrapper>
            <Card
                onClick={handleCardClick}
                bordered={false}
            >
                <Row gutter={[0, 12]}>
                    <Col span={24}>
                        <LogoContainer>
                            <Image src={logoSrc || FALLBACK_LOGO} height={24} style={IMAGE_STYLES} preview={false} fallback={FALLBACK_LOGO}/>
                        </LogoContainer>
                    </Col>
                    <Col span={24}>
                        <Typography.Paragraph style={TEXT_BLOCK_STYLE} ellipsis={{ rows: 2 }}>
                            <Typography.Title level={5} style={TEXT_STYLE}>
                                {title}
                            </Typography.Title>
                        </Typography.Paragraph>
                    </Col>
                    <Col span={24}>
                        <Space size={10} direction={'horizontal'}>
                            <CheckIcon fill={'#222'}/>
                            <ConnectContainer>
                                {ConnectedLabel}
                            </ConnectContainer>
                        </Space>
                    </Col>
                </Row>
            </Card>
        </CardWrapper>
    )
}
Example #22
Source File: Comment.tsx    From condo with MIT License 5 votes vote down vote up
getFilePreviewByMimetype = (mimetype, url) => {
    if (mimetype.startsWith('image')) return <Image src={url} width={64} height={64} />

    return <CommentFileCard>{getIconByMimetype(mimetype)}</CommentFileCard>
}
Example #23
Source File: link.tsx    From Search-Next with GNU General Public License v3.0 5 votes vote down vote up
Link: React.FC<LinkProps> = (props) => {
  const { onChange, data } = props;

  const [url, setUrl] = React.useState<string>('');
  const [blur, setBlur] = React.useState<boolean>(false);
  const [isUrl, setIsUrl] = React.useState<boolean>(false);

  React.useEffect(() => {
    setUrl(data ? data.url : '');
    setIsUrl(true);
    setBlur(true);
  }, [data]);

  return (
    <div>
      <AccordionDetailItem
        title="在线图片地址"
        action={
          <TextField
            size="small"
            label="链接"
            value={url}
            placeholder="请输入图片链接"
            onFocus={() => setBlur(false)}
            onChange={(e) => {
              setIsUrl(false);
              setUrl(e.target.value);
            }}
            onBlur={(e) => {
              setBlur(true);
              const check = isHttpLink.test(url);
              if (!check && url.length > 0) {
                toast.error('请输入有效的链接');
                setIsUrl(false);
              }
              if (check && url.length > 0) {
                setIsUrl(true);
                onChange(url);
              }
            }}
          />
        }
      />
      {url && blur && isUrl && (
        <div
          className={classNames(
            'm-2 rounded overflow-hidden',
            css`
              .ant-image {
                display: block;
              }
            `,
          )}
        >
          <Image src={url} />
        </div>
      )}
    </div>
  );
}
Example #24
Source File: contact.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
export default function version() {
  return (
    <PageLayout
      title={
        <>
          <Icon component={SystemInfoSvg as any} /> 联系我们
        </>
      }
      hideCluster
    >
      <div style={{ padding: 10 }}>
        <div style={{ padding: 20 }}>
          <ul style={{ paddingLeft: 10 }}>
            <li>
              文档国外地址:
              <a href='https://n9e.github.io/' target='_blank'>
                https://n9e.github.io/
              </a>
            </li>
            <li>
              文档国内地址:
              <a href='https://n9e.gitee.io/' target='_blank'>
                https://n9e.gitee.io/
              </a>
            </li>
          </ul>
          <div style={{ display: 'flex' }}>
            <Card style={{ width: 250, marginRight: 10 }} cover={<Image style={{ border: '1px solid #efefef', height: 305 }} preview={false} src={'/image/wx_n9e.png'} />}>
              <Meta title={<div style={{ textAlign: 'center' }}>微信公众号</div>} />
            </Card>
            {/* <Card style={{ width: 250, marginRight: 10 }} cover={<Image style={{ border: '1px solid #efefef', height: 305 }} preview={false} src={'/image/dingtalk.png'} />}>
              <Meta title={<div style={{ textAlign: 'center' }}>钉钉交流群</div>} />
            </Card>
            <Card style={{ width: 250 }} cover={<Image style={{ border: '1px solid #efefef', height: 305 }} preview={false} src={'/image/zhihu.png'} />}>
              <Meta title={<div style={{ textAlign: 'center' }}>知乎话题</div>} />
            </Card> */}
          </div>
        </div>
      </div>
    </PageLayout>
  );
}
Example #25
Source File: index.tsx    From ant-simple-draw with MIT License 5 votes vote down vote up
Img: FC<FormProps<string | null>> = memo(function Img({ value, onChange }) {
  const [visible, setVisible] = useState<boolean>(false);

  const [url, setUrl] = useState<string | null>(null);

  const acceptCallback = useCallback(
    (val: string) => {
      setUrl(val);
      triggerChange(val);
    },
    [url],
  );
  const remove = () => {
    setUrl(null);
    triggerChange(null);
  };

  const triggerChange = useCallback(
    (changedValue: string | null) => {
      onChange && onChange(changedValue);
    },
    [url],
  );

  const styles = useMemo(() => {
    if (url) {
      return { width: '48%' };
    }
    return { width: '100%' };
  }, [url]);

  useEffect(() => {
    if (value) {
      setUrl(value);
    }
  }, [value]);

  return (
    <div className={style.image}>
      <div className={style.main}>{url ? <Image width={100} src={url} /> : null}</div>
      <div className={style.btn}>
        <Button style={{ ...styles }} onClick={() => setVisible(true)}>
          上传
        </Button>
        {url ? (
          <Button style={{ ...styles }} danger onClick={remove}>
            清除
          </Button>
        ) : null}
      </div>
      <ImageGallery
        visible={visible}
        onCancel={() => setVisible(false)}
        callBack={acceptCallback}
      />
    </div>
  );
})
Example #26
Source File: MarkdownDisplay.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
export function MarkdownDisplay({
  value,
  imagePreview = true,
}: MarkdownDisplayProps): React.ReactElement {
  const history = getHistory();
  const baseUrl = location.origin + history.createHref(history.location);

  const renderer = {
    link(href: string, title: string, text: string) {
      href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
      if (href === null) {
        return text;
      }
      if (href.startsWith("?")) {
        href = location.origin + location.pathname + href;
      }
      if (href.startsWith("#")) {
        href = location.origin + location.pathname + location.search + href;
      }
      let out = '<a href="' + escape(href) + '"';
      if (title) {
        out += ' title="' + title + '"';
      }
      out += ">" + text + "</a>";
      return out;
    },
    image(href: string, _title: string, text: string) {
      const imgId = uniqueId(text ?? "");
      if (imagePreview) {
        const errorImage =
          "data:image/png;base64,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";
        setTimeout(() => {
          ReactDOM.render(
            <Image src={href} alt={text} fallback={errorImage} />,
            document.getElementById(imgId)
          );
        });
        return `<div class="img-preview" id="${imgId}">
          <img src="${errorImage}">
        </div>`;
      } else {
        return `<img src="${href}" alt="${text}">`;
      }
    },
  } as Partial<marked.Renderer> as marked.Renderer;

  // https://marked.js.org/using_pro#use
  marked.use({ renderer });

  DOMPurify.setConfig({ ADD_ATTR: ["target"] });

  return (
    <div
      className={style.customMarkdown}
      dangerouslySetInnerHTML={{
        __html: DOMPurify.sanitize(
          marked(value || "", {
            baseUrl,
            breaks: true,
          })
        ),
      }}
    />
  );
}
Example #27
Source File: YakEnvironment.tsx    From yakit with GNU Affero General Public License v3.0 4 votes vote down vote up
YakEnvironment: React.FC<YakEnvironmentProp> = (props) => {
    const [connected, setConnected] = useState(false);
    const [host, setHost] = useState("127.0.0.1");
    const [port, setPort] = useState(8087);
    const [tls, setTls] = useState(false);
    const [password, setPassword] = useState("");
    const [caPem, setCaPem] = useState("");
    const [mode, setMode] = useState<"local" | "remote">("local");
    const [localLoading, setLocalLoading] = useState(false);
    const [historySelected, setHistorySelected] = useState(false);
    const [name, setName] = useState("");
    const [allowSave, setAllowSave] = useState(false);
    const [version, setVersion] = useState("-");
    const [existedProcess, setExistedProcesses] = useState<yakProcess[]>([]);

    useEffect(() => {
        ipcRenderer.invoke("yakit-version").then(setVersion)
    }, [])

    useEffect(() => {
        // setLocalError("");
        if (mode) {
            props.setMode(mode);
        }
        // setLocalYakStarted(false);

        if (mode !== "local") {
            return
        }

        setHost("127.0.0.1")
    }, [mode])

    const login = (newHost?: string, newPort?: number) => {
        setLocalLoading(true)
        // info("正在连接 ... Yak 核心引擎")
        let params = {
            host: newHost || host,
            port: newPort || port,
            password, caPem,
        };
        render.invoke("connect-yak", {...params}).then(() => {
                props.onConnected()
                if (mode === "remote" && allowSave) {
                    saveAuthInfo({
                        ...params, tls, name,
                    })
                }
            }
        ).catch(() => {
            notification["error"]({message: "设置 Yak gRPC 引擎地址失败"})
        }).finally(() => {
            setTimeout(() => {
                setLocalLoading(false)
            }, 200);
        })
    }

    if (!connected) {
        return <Spin
            spinning={localLoading}
        >
            <div style={{
                textAlign: "center",
                marginLeft: 150, marginRight: 150
            }}>
                <Image src={YakLogoBanner}
                       style={{marginTop: 120, marginBottom: 40}}
                       preview={false} width={400}
                />
                <br/>
                <Text style={{color: "#999"}}>社区专业版:{version}</Text>
                <SelectOne label={" "} colon={false} data={[
                    {value: "local", text: "本地模式(本地启动 Yak gRPC)"},
                    {value: "remote", text: "远程模式(TeamServer 模式)"}
                ]} value={mode} setValue={setMode}/>

                {mode === "local" && <>
                    <YakLocalProcess onConnected={((newPort: any, newHost: any) => {
                        login(newHost, newPort)
                    })} onProcess={setExistedProcesses}/>
                </>}

                <Form
                    style={{textAlign: "left"}}
                    onSubmitCapture={e => {
                        e.preventDefault()

                        // setLocalYakStarted(false)
                        setLocalLoading(false)

                        login()
                    }} labelCol={{span: 7}} wrapperCol={{span: 12}}>
                    {mode === "remote" && <>
                        <YakRemoteAuth onSelected={(info) => {
                            setHistorySelected(true);
                            setHost(info.host);
                            setPort(info.port);
                            setTls(info.tls);
                            setCaPem(info.caPem);
                            setPassword(info.password);
                        }}/>
                        <SwitchItem value={allowSave} setValue={setAllowSave} label={"保存历史连接"}/>
                        {allowSave && <InputItem
                            label={"连接名"}
                            value={name} setValue={setName}
                            help={"可选,如果填写了,将会保存历史记录,之后可以选择该记录"}
                        />}
                        <FormItem label={"Yak gRPC 主机地址"}>
                            <Input value={host} onChange={e => {
                                setHost(e.target.value)
                                props.onAddrChanged(`${e.target.value}:${port}`)
                            }} style={{width: "100%"}}/>
                        </FormItem>
                        <FormItem label={"Yak gRPC 端口"}>
                            <InputNumber
                                min={1} max={65535}
                                value={port}
                                style={{width: "100%"}}
                                onChange={e => {
                                    setPort(e)
                                    props.onAddrChanged(`${host}:${e}`)
                                }}
                            />
                        </FormItem>
                        <SwitchItem label={"启用通信加密认证TLS"} value={tls} setValue={e => {
                            setTls(e)
                            props.onTlsGRPC(e)
                        }}/>
                        {tls ? <>
                            <Form.Item
                                required={true} label={<div>
                                gRPC Root-CA 证书(PEM)
                                <Popover content={<div style={{width: 500}}>
                                    <Space direction={"vertical"} style={{width: "100%"}}>
                                        <div>需要 PEM 格式的证书</div>
                                        <div>在通过 <Tag>yak grpc --tls</Tag> 启动核心服务器的时候,会把 RootCA 打印到屏幕上,复制到该输入框即可:</div>
                                        <br/>
                                        <div>例如如下内容:</div>
                                        <div style={{width: 500, height: 400}}>
                                            <YakEditor readOnly={true} value={pemPlaceHolder}/>
                                        </div>
                                    </Space>
                                </div>}>
                                    <Button
                                        style={{color: "#2f74d0"}}
                                        icon={<QuestionCircleOutlined/>}
                                        type={"link"} ghost={true}
                                    />
                                </Popover>
                            </div>}
                            >
                                <div style={{height: 420}}>
                                    <YakEditor
                                        value={caPem} setValue={setCaPem} type={"pem"}
                                    />
                                </div>
                            </Form.Item>
                            <InputItem
                                label={"密码"}
                                setValue={setPassword}
                                value={password}
                                type={"password"}
                            />
                        </> : ""}
                    </>}
                    {mode !== "local" && <div style={{textAlign: "center"}}>
                        <Button
                            style={{
                                width: 480, height: 50,
                            }}
                            htmlType={"submit"}
                            type={"primary"}
                        >
                            <p style={{fontSize: 18, marginBottom: 0}}>Yakit 连接 Yak 核心引擎[{host}:{port}]</p>
                        </Button>
                    </div>}
                    <div style={{textAlign: "center"}}>
                        <Space style={{
                            color: '#888',
                            marginBottom: tls ? 200 : 0,
                        }}>
                            <Button type={"link"} onClick={() => {
                                showModal({
                                    title: "用户协议",
                                    content: <>
                                        {UserProtocol()}
                                    </>
                                })
                            }}>用户协议</Button>
                            <Button.Group>
                                <Button
                                    onClick={() => {
                                        let m = showModal({
                                            keyboard: false,
                                            title: "引擎升级管理页面",
                                            width: "50%",
                                            content: <>
                                                <YakUpgrade onFinished={() => {
                                                    m.destroy()
                                                }} existed={existedProcess}/>
                                            </>
                                        })
                                    }}
                                >
                                    <p
                                        style={{marginBottom: 0}}
                                    >核心引擎安装与升级</p>
                                </Button>
                                <Button
                                    onClick={() => {
                                        let m = showModal({
                                            keyboard: false,
                                            title: "Yakit 升级",
                                            width: "50%",
                                            content: <>
                                                <YakitUpgrade onFinished={() => {
                                                    m.destroy()
                                                }}/>
                                            </>
                                        })
                                    }}
                                >
                                    <p
                                        style={{marginBottom: 0}}
                                    >Yakit 升级</p>
                                </Button>
                            </Button.Group>

                        </Space>
                    </div>
                </Form>
            </div>
        </Spin>
    }

    return <div>

    </div>
}
Example #28
Source File: RenderMapInit.tsx    From amiya with MIT License 4 votes vote down vote up
install = (registerTableRender: (key: string, render: (props: RenderProps) => ReactNode) => void) => {
  registerTableRender('__options', ({ field, text }: RenderProps) => {
    let option = field.options.find((option: Option) => option.value === text)
    return option ? option.label : text
  })

  registerTableRender('__ellipsis', ({ text, field }: RenderProps) => {
    return (
      <Tooltip placement={field.placement || 'topLeft'} title={text}>
        <span>{text || ''}</span>
      </Tooltip>
    )
  })

  registerTableRender('datetime', ({ text, field }: RenderProps) => {
    if (!text) {
      return ''
    }
    return moment(text).format(field.format || 'YYYY-MM-DD HH:mm:ss')
  })

  registerTableRender('editable-cell-input', ({ text, field }: RenderProps) => {
    const inputRef = useRef<any>(null)

    return ({ editing, mode, save }: AnyKeyProps) => {
      useEffect(() => {
        if (editing && mode === 'col') {
          inputRef.current.focus()
        }
      }, [editing])
      return !editing ? (
        text
      ) : (
        <Input placeholder="请输入" {...field.contentProps} ref={inputRef} onBlur={save} onPressEnter={save} />
      )
    }
  })

  registerTableRender('editable-cell-select', ({ text, field }: RenderProps) => {
    const selectRef = useRef<any>(null)
    const options = field.options || []
    let label = ''
    if (Array.isArray(text)) {
      if (!text.length) {
        text = FORM_READONLY_EMPTY
      }
      label = text.map((item: any) => getValueByOptions(item, field.options)).join(field.splitText || '、')
    } else {
      label = getValueByOptions(text, field.options)
    }

    return ({ editing, save, mode }: AnyKeyProps) => {
      useEffect(() => {
        if (editing && mode === 'col') {
          selectRef.current.focus()
        }
      }, [editing])
      return !editing ? (
        label
      ) : (
        <AySelect
          placeholder="请选择"
          style={{ width: '100%' }}
          {...field.contentProps}
          ref={selectRef}
          options={options}
          onBlur={save}
        />
      )
    }
  })

  registerTableRender('image', ({ text, field }: RenderProps) => {
    return <Image width={100} {...field.props} src={text} />
  })

  registerTableRender('html', ({ text, field }: RenderProps) => {
    return <div dangerouslySetInnerHTML={{ __html: text }}></div>
  })

  registerTableRender('tags', ({ text, field }: RenderProps) => {
    if (!Array.isArray(text) || !field.colorMap) {
      return text
    }
    return text.map((item: string) => (
      <Tag key={item} color={field.colorMap[item]}>
        {item}
      </Tag>
    ))
  })

  registerTableRender('unit', ({ text, field }: RenderProps) => {
    return (
      <div>
        {field.prefix}
        {text}
        {field.suffix}
      </div>
    )
  })

  /**
   * 5
   * @decs 状态加文字
   *
   * @returns ReactNode
   */
  registerTableRender('status', ({ text, field }: AnyKeyProps) => {
    const { options = [] } = field
    return renderStatus(text, options, field.type)
  })
}
Example #29
Source File: index.tsx    From amiya with MIT License 4 votes vote down vote up
fields = [
  {
    title: <AySearchList.SelectionAll />,
    key: 'selection',
    width: 50,
    onCell,
    render: (value: string, record: Record) => (
      <AySearchList.Selection record={record} disabled={record.rowSpan === 0} />
    )
  },
  {
    title: '商品名称&店铺',
    key: 'name',
    onCell,
    width: 300,
    render: (value: string, record: Record) => {
      return (
        <div style={{ height: '100%' }}>
          <Space>
            <Image style={{ flexShrink: 0 }} src={record.image} width={80} height={80} />
            <div>
              <div>
                <a href={record.shopUrl}>
                  {record.details.length > 0 && <span style={{ color: 'orange' }}>[多规格]</span>}
                  {value}
                </a>
              </div>
              <span className="tag">{record.shopName}</span>
            </div>
          </Space>
        </div>
      )
    },
    search: {
      title: '商品名称',
      type: 'input-group',
      key: '__group',
      children: [
        {
          type: 'select',
          key: 'keywordType',
          options: [
            { label: '商品名称', value: 1 },
            { label: '规格名称', value: 2 }
          ],
          defaultValue: 1,
          allowClear: false,
          style: {
            width: 100
          }
        },
        {
          key: 'keyword',
          style: {
            width: `calc(100% - 100px)`
          }
        }
      ]
    }
  },
  {
    title: '父规格',
    key: 'spu',
    width: 120,
    search: {
      title: '规格',
      key: 'sku',
      type: 'select',
      style: {
        width: 120
      },
      options: [
        { label: '规格选项A', value: 1 },
        { label: '规格选项B', value: 2 }
      ]
    },
    render: (value: string) => value || '-',
    onCell
  },
  {
    table: false,
    search: {
      title: '排序',
      key: 'sort',
      type: 'select',
      style: {
        width: 120
      },
      options: [
        { label: '排序A', value: 1 },
        { label: '排序B', value: 2 }
      ]
    }
  },
  {
    title: '规格',
    dataIndex: ['child', 'name'],
    key: 'childName',
    render: (value: string, record: Record) => (
      <span>
        {value}
        <AySearchList.Selection style={{ display: 'none' }} record={record} disabled={record.rowSpan === 0} />
      </span>
    )
  },
  {
    title: '价格',
    dataIndex: ['child', 'price'],
    key: 'childPrice',
    align: 'right',
    renderType: 'unit',
    prefix: '¥'
  },
  {
    title: '库存',
    dataIndex: ['child', 'stock'],
    key: 'childStock',
    align: 'right',
    renderType: 'unit',
    prefix: 'x'
  },
  {
    title: '创建时间',
    width: 120,
    key: 'createDateTime',
    renderType: 'datetime',
    onCell
  },
  {
    title: '创建时间',
    width: 120,
    key: 'updateDatetime',
    renderType: 'datetime',
    onCell
  }
]