@ant-design/icons#DragOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#DragOutlined. 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: EditHead.tsx    From ant-extensions with MIT License 6 votes vote down vote up
EditHead: React.FC<{
  title: string;
  onRemove: () => void;
  onDragStart: React.DragEventHandler;
}> = React.memo(({ title, onRemove, onDragStart }) => (
  <div className="ant-ext-pm__head" draggable onDragStart={onDragStart}>
    <small>{title}</small>
    <div>
      <button>
        <DragOutlined />
      </button>
      <button onClick={(e) => [onRemove(), e.stopPropagation()]}>
        <DeleteOutlined />
      </button>
    </div>
  </div>
))
Example #2
Source File: Icon.tsx    From html2sketch with MIT License 4 votes vote down vote up
IconSymbol: FC = () => {
  return (
    <Row>
      {/*<CaretUpOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
      {/*/>*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
      {/*/>*/}
      {/*<StepBackwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      {/*<StepForwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      <StepForwardOutlined />
      <ShrinkOutlined />
      <ArrowsAltOutlined />
      <DownOutlined />
      <UpOutlined />
      <LeftOutlined />
      <RightOutlined />
      <CaretUpOutlined />
      <CaretDownOutlined />
      <CaretLeftOutlined />
      <CaretRightOutlined />
      <VerticalAlignTopOutlined />
      <RollbackOutlined />
      <FastBackwardOutlined />
      <FastForwardOutlined />
      <DoubleRightOutlined />
      <DoubleLeftOutlined />
      <VerticalLeftOutlined />
      <VerticalRightOutlined />
      <VerticalAlignMiddleOutlined />
      <VerticalAlignBottomOutlined />
      <ForwardOutlined />
      <BackwardOutlined />
      <EnterOutlined />
      <RetweetOutlined />
      <SwapOutlined />
      <SwapLeftOutlined />
      <SwapRightOutlined />
      <ArrowUpOutlined />
      <ArrowDownOutlined />
      <ArrowLeftOutlined />
      <ArrowRightOutlined />
      <LoginOutlined />
      <LogoutOutlined />
      <MenuFoldOutlined />
      <MenuUnfoldOutlined />
      <BorderBottomOutlined />
      <BorderHorizontalOutlined />
      <BorderInnerOutlined />
      <BorderOuterOutlined />
      <BorderLeftOutlined />
      <BorderRightOutlined />
      <BorderTopOutlined />
      <BorderVerticleOutlined />
      <PicCenterOutlined />
      <PicLeftOutlined />
      <PicRightOutlined />
      <RadiusBottomleftOutlined />
      <RadiusBottomrightOutlined />
      <RadiusUpleftOutlined />
      <RadiusUprightOutlined />
      <FullscreenOutlined />
      <FullscreenExitOutlined />
      <QuestionOutlined />
      <PauseOutlined />
      <MinusOutlined />
      <PauseCircleOutlined />
      <InfoOutlined />
      <CloseOutlined />
      <ExclamationOutlined />
      <CheckOutlined />
      <WarningOutlined />
      <IssuesCloseOutlined />
      <StopOutlined />
      <EditOutlined />
      <CopyOutlined />
      <ScissorOutlined />
      <DeleteOutlined />
      <SnippetsOutlined />
      <DiffOutlined />
      <HighlightOutlined />
      <AlignCenterOutlined />
      <AlignLeftOutlined />
      <AlignRightOutlined />
      <BgColorsOutlined />
      <BoldOutlined />
      <ItalicOutlined />
      <UnderlineOutlined />
      <StrikethroughOutlined />
      <RedoOutlined />
      <UndoOutlined />
      <ZoomInOutlined />
      <ZoomOutOutlined />
      <FontColorsOutlined />
      <FontSizeOutlined />
      <LineHeightOutlined />
      <SortAscendingOutlined />
      <SortDescendingOutlined />
      <DragOutlined />
      <OrderedListOutlined />
      <UnorderedListOutlined />
      <RadiusSettingOutlined />
      <ColumnWidthOutlined />
      <ColumnHeightOutlined />
      <AreaChartOutlined />
      <PieChartOutlined />
      <BarChartOutlined />
      <DotChartOutlined />
      <LineChartOutlined />
      <RadarChartOutlined />
      <HeatMapOutlined />
      <FallOutlined />
      <RiseOutlined />
      <StockOutlined />
      <BoxPlotOutlined />
      <FundOutlined />
      <SlidersOutlined />
      <AndroidOutlined />
      <AppleOutlined />
      <WindowsOutlined />
      <IeOutlined />
      <ChromeOutlined />
      <GithubOutlined />
      <AliwangwangOutlined />
      <DingdingOutlined />
      <WeiboSquareOutlined />
      <WeiboCircleOutlined />
      <TaobaoCircleOutlined />
      <Html5Outlined />
      <WeiboOutlined />
      <TwitterOutlined />
      <WechatOutlined />
      <AlipayCircleOutlined />
      <TaobaoOutlined />
      <SkypeOutlined />
      <FacebookOutlined />
      <CodepenOutlined />
      <CodeSandboxOutlined />
      <AmazonOutlined />
      <GoogleOutlined />
      <AlipayOutlined />
      <AntDesignOutlined />
      <AntCloudOutlined />
      <ZhihuOutlined />
      <SlackOutlined />
      <SlackSquareOutlined />
      <BehanceSquareOutlined />
      <DribbbleOutlined />
      <DribbbleSquareOutlined />
      <InstagramOutlined />
      <YuqueOutlined />
      <AlibabaOutlined />
      <YahooOutlined />
      <RedditOutlined />
      <SketchOutlined />
      <AccountBookOutlined />
      <AlertOutlined />
      <ApartmentOutlined />
      <ApiOutlined />
      <QqOutlined />
      <MediumWorkmarkOutlined />
      <GitlabOutlined />
      <MediumOutlined />
      <GooglePlusOutlined />
      <AppstoreAddOutlined />
      <AppstoreOutlined />
      <AudioOutlined />
      <AudioMutedOutlined />
      <AuditOutlined />
      <BankOutlined />
      <BarcodeOutlined />
      <BarsOutlined />
      <BellOutlined />
      <BlockOutlined />
      <BookOutlined />
      <BorderOutlined />
      <BranchesOutlined />
      <BuildOutlined />
      <BulbOutlined />
      <CalculatorOutlined />
      <CalendarOutlined />
      <CameraOutlined />
      <CarOutlined />
      <CarryOutOutlined />
      <CiCircleOutlined />
      <CiOutlined />
      <CloudOutlined />
      <ClearOutlined />
      <ClusterOutlined />
      <CodeOutlined />
      <CoffeeOutlined />
      <CompassOutlined />
      <CompressOutlined />
      <ContactsOutlined />
      <ContainerOutlined />
      <ControlOutlined />
      <CopyrightCircleOutlined />
      <CopyrightOutlined />
      <CreditCardOutlined />
      <CrownOutlined />
      <CustomerServiceOutlined />
      <DashboardOutlined />
      <DatabaseOutlined />
      <DeleteColumnOutlined />
      <DeleteRowOutlined />
      <DisconnectOutlined />
      <DislikeOutlined />
      <DollarCircleOutlined />
      <DollarOutlined />
      <DownloadOutlined />
      <EllipsisOutlined />
      <EnvironmentOutlined />
      <EuroCircleOutlined />
      <EuroOutlined />
      <ExceptionOutlined />
      <ExpandAltOutlined />
      <ExpandOutlined />
      <ExperimentOutlined />
      <ExportOutlined />
      <EyeOutlined />
      <FieldBinaryOutlined />
      <FieldNumberOutlined />
      <FieldStringOutlined />
      <DesktopOutlined />
      <DingtalkOutlined />
      <FileAddOutlined />
      <FileDoneOutlined />
      <FileExcelOutlined />
      <FileExclamationOutlined />
      <FileOutlined />
      <FileImageOutlined />
      <FileJpgOutlined />
      <FileMarkdownOutlined />
      <FilePdfOutlined />
      <FilePptOutlined />
      <FileProtectOutlined />
      <FileSearchOutlined />
      <FileSyncOutlined />
      <FileTextOutlined />
      <FileUnknownOutlined />
      <FileWordOutlined />
      <FilterOutlined />
      <FireOutlined />
      <FlagOutlined />
      <FolderAddOutlined />
      <FolderOutlined />
      <FolderOpenOutlined />
      <ForkOutlined />
      <FormatPainterOutlined />
      <FrownOutlined />
      <FunctionOutlined />
      <FunnelPlotOutlined />
      <GatewayOutlined />
      <GifOutlined />
      <GiftOutlined />
      <GlobalOutlined />
      <GoldOutlined />
      <GroupOutlined />
      <HddOutlined />
      <HeartOutlined />
      <HistoryOutlined />
      <HomeOutlined />
      <HourglassOutlined />
      <IdcardOutlined />
      <ImportOutlined />
      <InboxOutlined />
      <InsertRowAboveOutlined />
      <InsertRowBelowOutlined />
      <InsertRowLeftOutlined />
      <InsertRowRightOutlined />
      <InsuranceOutlined />
      <InteractionOutlined />
      <KeyOutlined />
      <LaptopOutlined />
      <LayoutOutlined />
      <LikeOutlined />
      <LineOutlined />
      <LinkOutlined />
      <Loading3QuartersOutlined />
      <LoadingOutlined />
      <LockOutlined />
      <MailOutlined />
      <ManOutlined />
      <MedicineBoxOutlined />
      <MehOutlined />
      <MenuOutlined />
      <MergeCellsOutlined />
      <MessageOutlined />
      <MobileOutlined />
      <MoneyCollectOutlined />
      <MonitorOutlined />
      <MoreOutlined />
      <NodeCollapseOutlined />
      <NodeExpandOutlined />
      <NodeIndexOutlined />
      <NotificationOutlined />
      <NumberOutlined />
      <PaperClipOutlined />
      <PartitionOutlined />
      <PayCircleOutlined />
      <PercentageOutlined />
      <PhoneOutlined />
      <PictureOutlined />
      <PoundCircleOutlined />
      <PoundOutlined />
      <PoweroffOutlined />
      <PrinterOutlined />
      <ProfileOutlined />
      <ProjectOutlined />
      <PropertySafetyOutlined />
      <PullRequestOutlined />
      <PushpinOutlined />
      <QrcodeOutlined />
      <ReadOutlined />
      <ReconciliationOutlined />
      <RedEnvelopeOutlined />
      <ReloadOutlined />
      <RestOutlined />
      <RobotOutlined />
      <RocketOutlined />
      <SafetyCertificateOutlined />
      <SafetyOutlined />
      <ScanOutlined />
      <ScheduleOutlined />
      <SearchOutlined />
      <SecurityScanOutlined />
      <SelectOutlined />
      <SendOutlined />
      <SettingOutlined />
      <ShakeOutlined />
      <ShareAltOutlined />
      <ShopOutlined />
      <ShoppingCartOutlined />
      <ShoppingOutlined />
      <SisternodeOutlined />
      <SkinOutlined />
      <SmileOutlined />
      <SolutionOutlined />
      <SoundOutlined />
      <SplitCellsOutlined />
      <StarOutlined />
      <SubnodeOutlined />
      <SyncOutlined />
      <TableOutlined />
      <TabletOutlined />
      <TagOutlined />
      <TagsOutlined />
      <TeamOutlined />
      <ThunderboltOutlined />
      <ToTopOutlined />
      <ToolOutlined />
      <TrademarkCircleOutlined />
      <TrademarkOutlined />
      <TransactionOutlined />
      <TrophyOutlined />
      <UngroupOutlined />
      <UnlockOutlined />
      <UploadOutlined />
      <UsbOutlined />
      <UserAddOutlined />
      <UserDeleteOutlined />
      <UserOutlined />
      <UserSwitchOutlined />
      <UsergroupAddOutlined />
      <UsergroupDeleteOutlined />
      <VideoCameraOutlined />
      <WalletOutlined />
      <WifiOutlined />
      <BorderlessTableOutlined />
      <WomanOutlined />
      <BehanceOutlined />
      <DropboxOutlined />
      <DeploymentUnitOutlined />
      <UpCircleOutlined />
      <DownCircleOutlined />
      <LeftCircleOutlined />
      <RightCircleOutlined />
      <UpSquareOutlined />
      <DownSquareOutlined />
      <LeftSquareOutlined />
      <RightSquareOutlined />
      <PlayCircleOutlined />
      <QuestionCircleOutlined />
      <PlusCircleOutlined />
      <PlusSquareOutlined />
      <MinusSquareOutlined />
      <MinusCircleOutlined />
      <InfoCircleOutlined />
      <ExclamationCircleOutlined />
      <CloseCircleOutlined />
      <CloseSquareOutlined />
      <CheckCircleOutlined />
      <CheckSquareOutlined />
      <ClockCircleOutlined />
      <FormOutlined />
      <DashOutlined />
      <SmallDashOutlined />
      <YoutubeOutlined />
      <CodepenCircleOutlined />
      <AliyunOutlined />
      <PlusOutlined />
      <LinkedinOutlined />
      <AimOutlined />
      <BugOutlined />
      <CloudDownloadOutlined />
      <CloudServerOutlined />
      <CloudSyncOutlined />
      <CloudUploadOutlined />
      <CommentOutlined />
      <ConsoleSqlOutlined />
      <EyeInvisibleOutlined />
      <FileGifOutlined />
      <DeliveredProcedureOutlined />
      <FieldTimeOutlined />
      <FileZipOutlined />
      <FolderViewOutlined />
      <FundProjectionScreenOutlined />
      <FundViewOutlined />
      <MacCommandOutlined />
      <PlaySquareOutlined />
      <OneToOneOutlined />
      <RotateLeftOutlined />
      <RotateRightOutlined />
      <SaveOutlined />
      <SwitcherOutlined />
      <TranslationOutlined />
      <VerifiedOutlined />
      <VideoCameraAddOutlined />
      <WhatsAppOutlined />

      {/*</Col>*/}
    </Row>
  );
}
Example #3
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
AutoReply: React.FC<AutoReplyProps> = (props) => {
  const {welcomeMsg, setWelcomeMsg, isFetchDone} = props;
  const [modalVisible, setModalVisible] = useState(false);
  const [attachments, setAttachments] = useState<Attachment[]>([]);
  const [currentIndex, setCurrentIndex] = useState<number>(0);
  const [currentMode, setCurrentMode] = useState<MsgType>('image');
  const [linkFetching, setLinkFetching] = useState(false);
  const [content, setContent] = useState('');
  const contentRef = useRef<React.RefObject<HTMLElement>>();
  const imageModalFormRef = useRef<FormInstance>();
  const linkModalFormRef = useRef<FormInstance>();
  const miniAppModalFormRef = useRef<FormInstance>();

  const UploadFileFn = async (req: UploadRequestOption, ref: MutableRefObject<any | undefined>, inputName: string) => {
    const file = req.file as File;
    if (!file.name) {
      message.error('非法参数');
      return;
    }

    const hide = message.loading('上传中');
    try {
      const res = await GetSignedURL(file.name)
      const data = res.data as GetSignedURLResult
      if (res.code === 0) {
        const uploadRes = (await fetch(data.upload_url, {
          method: 'PUT',
          body: file
        }));
        hide();
        if (uploadRes.ok && ref) {
          ref.current?.setFieldsValue({[inputName]: data.download_url});
          return;
        }

        message.error('上传图片失败');

        return;
      }

      hide();
      message.error('获取上传地址失败');
      return;

    } catch (e) {
      message.error('上传图片失败');
      console.log(e);
    }
  };

  useEffect(() => {
    const formData = itemDataToFormData(welcomeMsg);
    setAttachments(formData.attachments || []);
    setContent(formData.text || '');
  }, [isFetchDone]);

  useEffect(() => {
    setWelcomeMsg({
      text: content || '',
      attachments: attachments || [],
    });
  }, [content, attachments]);

  return (
    <>
      <div className={styles.replyEditor}>
        <div className={'preview-container'}>
          <div className={styles.replyEditorPreview}>
            <img src={phoneImage} className='bg'/>
            <div className='content'>
              <ul className='reply-list'>
                {content && (
                  <li><img
                    src={avatarDefault}/>
                    <div className='msg text' dangerouslySetInnerHTML={{__html: content}}/>
                  </li>
                )}
                {attachments && attachments.length > 0 && (
                  attachments.map((attachment) => {
                    if (attachment.msgtype === 'image') {
                      return (
                        <li key={attachment.id}>
                          <img src={avatarDefault}/>
                          <div className={`msg image`}>
                            <img src={attachment.image?.pic_url}/>
                          </div>
                        </li>
                      );
                    }

                    if (attachment.msgtype === 'link') {
                      return (
                        <li key={attachment.id}>
                          <img src={avatarDefault}/>
                          <div className='msg link'><p className='title'>{attachment.link?.title}</p>
                            <div className='link-inner'><p
                              className='desc'>{attachment.link?.desc}</p>
                              <img src={attachment.link?.picurl}/>
                            </div>
                          </div>
                        </li>
                      );
                    }

                    if (attachment.msgtype === 'miniprogram') {
                      return (
                        <li key={attachment.id}>
                          <img src={avatarDefault}/>
                          <div className='msg miniprogram'>
                            <p className='m-title'>
                              <IconFont
                                type={'icon-weixin-mini-app'}
                                style={{marginRight: 4, fontSize: 14}}
                              />
                              {attachment.miniprogram?.title}
                            </p>
                            <img src={attachment.miniprogram?.pic_media_id}/>
                            <p className='l-title'>
                              <IconFont type={'icon-weixin-mini-app'} style={{marginRight: 4}}/>
                              小程序
                            </p>
                          </div>
                        </li>
                      );
                    }

                    return '';
                  })
                )}
              </ul>
            </div>
          </div>
        </div>

        <div className='text-area-container'>
          <div className={styles.msgTextareaContainer} style={{border: 'none'}}>
            {props.enableQuickInsert && (
              <div className='insert-btn '>
                    <span
                      className='clickable no-select'
                      onClick={() => {
                        setContent(`${content}[客户昵称]`);
                      }}
                    >[插入客户昵称]</span>
              </div>
            )}
            <div className='textarea-container '>
              <ContentEditable
                // @ts-ignore
                innerRef={contentRef}
                onKeyDown={(event) => {
                  if (event.key === 'Enter') {
                    document.execCommand('insertLineBreak');
                    event.preventDefault();
                  }
                }}
                className={'textarea'}
                html={content}
                onChange={(e) => {
                  setContent(e.target.value);
                }}/>
              <div className='flex-row align-side'>
                <p className='text-cnt'>{content.length}/600</p>
              </div>
            </div>
          </div>
        </div>
        <div className='option-area-container'>
          {attachments && attachments.length > 0 && (
            <ReactSortable handle={'.draggable-button'} tag='ul' className={'select-msg-options'} list={attachments} setList={setAttachments}>
              {attachments.map((attachment, index) => (
                <li key={attachment.id} className='flex-row'>
                      <span>
                        <MinusCircleOutlined
                          onClick={() => {
                            const items = [...attachments];
                            items.splice(index, 1);
                            setAttachments(items);
                          }}
                        />
                        【{msgTypes[attachment.msgtype]}】:
                        <span
                          className='col-1'>{attachment?.name}</span>
                      </span>
                  <span className='d-action-container'>
                      <EditOutlined
                        onClick={() => {
                          setCurrentMode(attachment.msgtype);
                          imageModalFormRef.current?.setFieldsValue(attachment.image);
                          linkModalFormRef.current?.setFieldsValue(attachment.link);
                          miniAppModalFormRef.current?.setFieldsValue(attachment.miniprogram);
                          setCurrentIndex(index);
                          setModalVisible(true);
                        }}
                      />
                      <DragOutlined
                        className={'draggable-button'}
                        style={{cursor: 'grabbing'}}
                      />
                    </span>
                </li>
              ))}
            </ReactSortable>
          )}
          <div className='option-container'>
            <Dropdown
              placement='topLeft'
              trigger={['click']}
              overlay={(
                <Menu style={{minWidth: 120}}>
                  <Menu.Item
                    key={'image'}
                    icon={<FileImageOutlined/>}
                    onClick={() => {
                      setCurrentMode('image');
                      setCurrentIndex(attachments.length);
                      imageModalFormRef.current?.resetFields();
                      setModalVisible(true);
                    }}
                  >
                    图片
                  </Menu.Item>
                  <Menu.Item
                    key={'link'}
                    icon={<LinkOutlined/>}
                    onClick={() => {
                      setCurrentMode('link');
                      setCurrentIndex(attachments.length);
                      setModalVisible(true);
                    }}
                  >
                    链接
                  </Menu.Item>
                  <Menu.Item
                    key={'miniApp'}
                    icon={<IconFont type={'icon-weixin-mini-app'}/>}
                    onClick={() => {
                      setCurrentMode('miniprogram');
                      setCurrentIndex(attachments.length);
                      setModalVisible(true);
                    }}
                  >
                    小程序
                  </Menu.Item>
                </Menu>
              )}
            >
              <a className='ant-dropdown-link' onClick={e => e.preventDefault()}>
                <PlusCircleOutlined/> 添加附件
              </a>
            </Dropdown>
          </div>
        </div>
      </div>

      <ModalForm
        formRef={imageModalFormRef}
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        width={'560px'}
        visible={currentMode === 'image' && modalVisible}
        onVisibleChange={setModalVisible}
        onFinish={async (params: { title: string, pic_url: string, msgtype: MsgType }) => {
          attachments[currentIndex] = {
            id: new Date().getTime().toString(),
            msgtype: params.msgtype,
            name: params.title,
            image: {...params},
          };
          setAttachments(attachments);
          return true;
        }}
      >
        <h2 className='dialog-title'> 添加图片附件 </h2>
        <ProForm.Item initialValue={'image'} name={'msgtype'} noStyle={true}>
          <input type={'hidden'}/>
        </ProForm.Item>
        <ProFormText
          name='title'
          label='图片名称'
          placeholder={'请输入图片名称'}
          width='md'
          rules={[
            {
              required: true,
              message: '请输入图片名称!',
            },
          ]}
        />
        <Form.Item
          label='上传图片'
          name='pic_url'
          rules={[
            {
              required: true,
              message: '请上传图片!',
            },
          ]}
        >
          <ImageUploader
            customRequest={async (req) => {
              await UploadFileFn(req, imageModalFormRef, 'pic_url')
            }}
          />
        </Form.Item>
      </ModalForm>


      <ModalForm
        formRef={linkModalFormRef}
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        width={'560px'}
        visible={currentMode === 'link' && modalVisible}
        onVisibleChange={setModalVisible}
        onFinish={async (params) => {
          attachments[currentIndex] = {
            id: new Date().getTime().toString(),
            msgtype: params.msgtype,
            name: params.title,
            // @ts-ignore
            link: {...params},
          };
          setAttachments(attachments);
          return true;
        }}
      >
        <Spin spinning={linkFetching}>
          <h2 className='dialog-title'> 添加链接附件 </h2>
          <ProForm.Item initialValue={'link'} name={'msgtype'} noStyle={true}>
            <input type={'hidden'}/>
          </ProForm.Item>
          <ProFormText
            name='url'
            label='链接地址'
            width='md'
            fieldProps={{
              disabled: linkFetching,
              addonAfter: (
                <Tooltip title="点击抓取远程链接,自动填充标题,描述,图片">
                  <div
                    onClick={async () => {
                      setLinkFetching(true);
                      const res = await ParseURL(linkModalFormRef.current?.getFieldValue('url'))
                      setLinkFetching(false);
                      if (res.code !== 0) {
                        message.error(res.message);
                      } else {
                        message.success('解析链接成功');
                        linkModalFormRef?.current?.setFieldsValue({
                          customer_link_enable: 1,
                          title: res.data.title,
                          desc: res.data.desc,
                          picurl: res.data.img_url,
                        })
                      }
                    }}
                    style={{
                      cursor: "pointer",
                      width: 32,
                      height: 30,
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center'
                    }}>
                    <SyncOutlined/>
                  </div>
                </Tooltip>
              )
            }}
            rules={[
              {
                required: true,
                message: '请输入链接地址',
              },
              {
                type: 'url',
                message: '请填写正确的的URL,必须是http或https开头',
              },
            ]}
          />
          <ProFormSwitch
            label={'高级设置'}
            checkedChildren='开启'
            unCheckedChildren='关闭'
            name='customer_link_enable'
            tooltip={'开启后可以自定义链接所有信息'}
          />
          <ProFormDependency name={['customer_link_enable']}>
            {({customer_link_enable}) => {
              if (customer_link_enable) {
                return (
                  <>
                    <ProFormText
                      name='title'
                      label='链接标题'
                      width='md'
                      rules={[
                        {
                          required: true,
                          message: '请输入链接标题',
                        },
                      ]}
                    />
                    <ProFormTextArea
                      name='desc'
                      label='链接描述'
                      width='md'
                    />
                    <Form.Item
                      label='链接封面'
                      name='picurl'
                      rules={[
                        {
                          required: true,
                          message: '请上传链接图片!',
                        },
                      ]}
                    >
                      <ImageUploader
                        customRequest={async (req) => {
                          await UploadFileFn(req, linkModalFormRef, 'picurl')
                        }}
                      />
                    </Form.Item>
                  </>
                );
              }
              return <></>;
            }}
          </ProFormDependency>
        </Spin>
      </ModalForm>


      <ModalForm
        formRef={miniAppModalFormRef}
        className={'dialog from-item-label-100w'}
        layout={'horizontal'}
        width={'560px'}
        labelCol={{
          md: 6,
        }}
        visible={currentMode === 'miniprogram' && modalVisible}
        onVisibleChange={setModalVisible}
        onFinish={async (params) => {
          attachments[currentIndex] = {
            id: new Date().getTime().toString(),
            msgtype: params.msgtype,
            name: params.title,
            // @ts-ignore
            miniprogram: {...params},
          };
          setAttachments(attachments);
          return true;
        }}
      >
        <h2 className='dialog-title'> 添加小程序附件 </h2>

        <Alert
          showIcon={true}
          type='info'
          message={
            '请填写企业微信后台绑定的小程序id和路径,否则会造成发送失败'
          }
          style={{marginBottom: 20}}
        />

        <ProForm.Item initialValue={'miniprogram'} name={'msgtype'} noStyle={true}>
          <input type={'hidden'}/>
        </ProForm.Item>

        <ProFormText
          name='title'
          label='小程序标题'
          width='md'
          rules={[
            {
              required: true,
              message: '请输入链接标题',
            },
          ]}
        />

        <ProFormText
          // 帮助指引
          name='app_id'
          label='小程序AppID'
          width='md'
          rules={[
            {
              required: true,
              message: '请输入小程序AppID',
            },
          ]}
        />

        <ProFormText
          name='page'
          label='小程序路径'
          width='md'
          rules={[
            {
              required: true,
              message: '请输入小程序路径',
            },
          ]}
        />

        <Form.Item
          label='小程序封面'
          name='pic_media_id'
          rules={[
            {
              required: true,
              message: '请小程序封面!',
            },
          ]}
        >
          <ImageUploader
            customRequest={async (req) => {
              await UploadFileFn(req, miniAppModalFormRef, 'pic_media_id')
            }}
          />
        </Form.Item>

      </ModalForm>

    </>
  );
}
Example #4
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
CustomerTagGroupList: React.FC = () => {
  const [currentItem, setCurrentItem] = useState<CustomerTagGroupItem>({});
  const [tagGroups, setTagGroups] = useState<CustomerTagGroupItem[]>([]);
  const [createModalVisible, setCreateModalVisible] = useState<boolean>(false);
  const [editModalVisible, setEditModalVisible] = useState<boolean>(false);
  const [syncLoading, setSyncLoading] = useState<boolean>(false);
  const [actionLoading, setActionLoading] = useState<boolean>(false);
  const [inputLoading, setInputLoading] = useState<boolean>(false);
  const [minOrder, setMinOrder] = useState<number>(10000);
  const [maxOrder, setMaxOrder] = useState<number>(100000);
  const [currentInputTagGroupExtID, setCurrentInputTagGroupExtID] = useState<string>();
  const [allDepartments, setAllDepartments] = useState<DepartmentOption[]>([]);
  const [allDepartmentMap, setAllDepartmentMap] = useState<Dictionary<DepartmentOption>>({});
  const queryFilterFormRef = useRef<FormInstance>();

  useEffect(() => {
    QueryDepartment({page_size: 5000}).then((res) => {
      if (res.code === 0) {
        const departments =
          res?.data?.items?.map((item: DepartmentInterface) => {
            return {
              label: item.name,
              value: item.ext_id,
              ...item,
            };
          }) || [];
        setAllDepartments(departments);
        setAllDepartmentMap(_.keyBy<DepartmentOption>(departments, 'ext_id'));

      } else {
        message.error(res.message);
      }
    });
    queryFilterFormRef.current?.submit();
  }, []);

  // @ts-ignore
  // @ts-ignore
  return (
    <PageContainer
      fixedHeader
      header={{
        title: '客户标签管理',
      }}
      extra={[
        <Button
          key='create'
          type='primary'
          icon={<PlusOutlined style={{fontSize: 16, verticalAlign: '-3px'}}/>}
          onClick={() => {
            setCreateModalVisible(true);
          }}
        >
          添加标签组
        </Button>,

        <Button
          key={'sync'}
          type='dashed'
          icon={<SyncOutlined style={{fontSize: 16, verticalAlign: '-3px'}}/>}
          loading={syncLoading}
          onClick={async () => {
            setSyncLoading(true);
            const res: CommonResp = await Sync();
            if (res.code === 0) {
              setSyncLoading(false);
              message.success('同步成功');
              queryFilterFormRef.current?.submit();
            } else {
              setSyncLoading(false);
              message.error(res.message);
            }
          }}
        >
          同步企业微信标签
        </Button>,
      ]}
    >
      <ProCard className={styles.queryFilter}>
        <QueryFilter
          formRef={queryFilterFormRef}
          onReset={() => {
            queryFilterFormRef.current?.submit();
          }}
          onFinish={async (params: any) => {
            setActionLoading(true);
            const res: CommonResp = await Query({
              ...params,
              page_size: 5000,
              sort_field: 'order',
              sort_type: 'desc',
            });
            setActionLoading(false);
            if (res.code === 0) {
              setTagGroups(res.data.items);
              if (res.data?.items[0]) {
                setMaxOrder(res.data.items[0]?.order);
              }
              if (res.data?.items.length >= 1 && res.data?.items[res.data?.items.length - 1]) {
                let min = res.data?.items[res.data?.items.length - 1];
                min = min - 1 >= 0 ? min - 1 : 0;
                setMinOrder(min);
              }
            } else {
              message.error('查询标签失败');
              setTagGroups([]);
            }
          }}
        >
          <Form.Item label='可用部门' name='ext_department_ids'>
            <DepartmentTreeSelect
              onChange={() => {
                queryFilterFormRef.current?.submit();
              }}
              options={allDepartments}
            />
          </Form.Item>

          <ProFormText width={'md'} name='name' label='搜索' placeholder='请输入关键词'/>

        </QueryFilter>
      </ProCard>

      <ProCard style={{marginTop: 12}} bodyStyle={{paddingTop: 0}} gutter={0}>
        <Spin spinning={actionLoading}>
          {(!tagGroups || tagGroups.length === 0) && <Empty style={{marginTop: 36, marginBottom: 36}}/>}
          {tagGroups && tagGroups.length > 0 && (
            <ReactSortable<any>
              handle={'.draggable-button'}
              className={styles.tagGroupList}
              list={tagGroups}
              setList={setTagGroups}
              swap={true}
              onEnd={async (e) => {
                // @ts-ignore
                const from = tagGroups[e.newIndex];
                // @ts-ignore
                const to = tagGroups[e.oldIndex];
                const res = await ExchangeOrder({id: from.id, exchange_order_id: to.id});
                if (res.code !== 0) {
                  message.error(res.message)
                }
              }}
            >
              {tagGroups.map((tagGroup) => (
                <Row className={styles.tagGroupItem} data-id={tagGroup.id} key={tagGroup.ext_id}>
                  <Col md={4} className={styles.tagName}>
                    <h4>{tagGroup.name}</h4>
                  </Col>
                  <Col md={16} className={styles.tagList}>
                    <Row>
                      可见范围:
                      {tagGroup.department_list && !tagGroup.department_list.includes(0) ? (
                        <Space direction={'horizontal'} wrap={true} style={{marginBottom: 6}}>
                          {tagGroup.department_list.map((id) => (
                            <div key={id}>
                            <span>
                              <FolderFilled
                                style={{
                                  color: '#47a7ff',
                                  fontSize: 20,
                                  marginRight: 6,
                                  verticalAlign: -6,
                                }}
                              />
                              {allDepartmentMap[id]?.name}
                            </span>
                            </div>
                          ))}
                        </Space>
                      ) : (
                        <span>全部员工可见</span>
                      )}
                    </Row>
                    <Row style={{marginTop: 12}}>
                      <Space direction={'horizontal'} wrap={true}>
                        <Button
                          icon={<PlusOutlined/>}
                          onClick={() => {
                            setCurrentInputTagGroupExtID(tagGroup.ext_id);
                          }}
                        >
                          添加
                        </Button>

                        {currentInputTagGroupExtID === tagGroup.ext_id && (
                          <Input
                            autoFocus={true}
                            disabled={inputLoading}
                            placeholder='逗号分隔,回车保存'
                            onBlur={() => setCurrentInputTagGroupExtID('')}
                            onPressEnter={async (e) => {
                              setInputLoading(true);
                              const res = await CreateTag({
                                names: e.currentTarget.value
                                  .replace(',', ',')
                                  .split(',')
                                  .filter((val) => val),
                                ext_tag_group_id: tagGroup.ext_id || '',
                              });
                              if (res.code === 0) {
                                setCurrentInputTagGroupExtID('');
                                tagGroup.tags?.unshift(...res.data);
                              } else {
                                message.error(res.message);
                              }
                              setInputLoading(false);
                            }}
                          />
                        )}
                        {tagGroup.tags?.map((tag) => (
                          <Tag className={styles.tagItem} key={tag.id}>
                            {tag.name}
                          </Tag>
                        ))}
                      </Space>
                    </Row>
                  </Col>
                  <Col md={4} className={styles.groupAction}>
                    <Tooltip title="拖动可实现排序" trigger={['click']}>
                      <Button
                        className={'draggable-button'}
                        icon={<DragOutlined
                          style={{cursor: 'grabbing'}}
                        />}
                        type={'text'}
                      >
                        排序
                      </Button>
                    </Tooltip>

                    <Button
                      icon={<EditOutlined/>}
                      type={'text'}
                      onClick={() => {
                        setCurrentItem(tagGroup);
                        setEditModalVisible(true);
                      }}
                    >
                      修改
                    </Button>
                    <Button
                      icon={<DeleteOutlined/>}
                      type={'text'}
                      onClick={() => {
                        Modal.confirm({
                          title: `删除标签分组`,
                          content: `是否确认删除「${tagGroup.name}」分组?`,
                          okText: '删除',
                          okType: 'danger',
                          cancelText: '取消',
                          onOk() {
                            return HandleRequest({ext_ids: [tagGroup.ext_id]}, Delete, () => {
                              queryFilterFormRef.current?.submit();
                            });
                          },
                        });
                      }}
                    >
                      删除
                    </Button>
                  </Col>
                </Row>
              ))}
            </ReactSortable>
          )}
        </Spin>
      </ProCard>

      <CreateModalForm
        // 创建标签
        type={'create'}
        minOrder={minOrder}
        maxOrder={maxOrder}
        allDepartments={allDepartments}
        setVisible={setCreateModalVisible}
        initialValues={{tags: [{name: ''}], department_list: [0]}}
        visible={createModalVisible}
        onFinish={async (values) => {
          await HandleRequest(values, Create, () => {
            queryFilterFormRef.current?.submit();
            setCreateModalVisible(false);
          });
        }}
      />

      <CreateModalForm
        // 修改标签
        type={'edit'}
        destroyOnClose={true}
        minOrder={minOrder}
        maxOrder={maxOrder}
        allDepartments={allDepartments}
        setVisible={setEditModalVisible}
        visible={editModalVisible}
        initialValues={currentItem}
        onFinish={async (values) => {
          await HandleRequest(values, Update, () => {
            queryFilterFormRef.current?.submit();
            setEditModalVisible(false);
          });
        }}
      />
    </PageContainer>
  );
}