@ant-design/icons#QrcodeOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#QrcodeOutlined. 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: Account.tsx    From nanolooker with MIT License 5 votes vote down vote up
AccountHeader: React.FC<Props> = ({
  account,
  isLink = false,
  hideOptions = false,
}) => {
  const { natricons } = React.useContext(PreferencesContext);
  const isSmallAndLower = !useMediaQuery("(min-width: 576px)");

  return (
    <div
      style={{
        display: "flex",
        alignItems: natricons ? "center" : "",
        fontSize: "16px",
        wordWrap: "break-word",
        position: "relative",
      }}
      className="color-normal"
    >
      {natricons ? (
        <Natricon
          account={account}
          style={{
            margin: "-12px -6px -18px -18px",
            width: "80px",
            height: "80px",
          }}
        />
      ) : (
        <div style={{ alignSelf: "baseline" }}>
          <WalletOutlined
            style={{
              fontSize: "18px",
              marginRight: "6px",
            }}
          />
        </div>
      )}

      {!isLink ? (
        <span className="break-word" style={{ marginRight: "6px" }}>
          <span>
            {account.substr(account.length * -1, account.length - 60)}
          </span>
          <span style={{ color: "#1890ff" }}>{account.substr(-60, 7)}</span>
          <span>{account.substr(-53, 46)}</span>
          <span style={{ color: "#1890ff" }}>{account.substr(-7)}</span>
        </span>
      ) : (
        <Link
          to={`/account/${account}`}
          style={{ fontSize: "14px", marginRight: "6px" }}
          className="break-word"
        >
          {account}
        </Link>
      )}

      {!hideOptions ? (
        <Row gutter={6} justify="start" className="options-wrapper">
          <Col style={{ fontSize: 0, alignSelf: "center" }}>
            <Copy text={account} />
          </Col>
          <Col>
            <Bookmark
              type="account"
              bookmark={account}
              placement={isSmallAndLower ? "left" : "top"}
            />
          </Col>
          <Col>
            <QRCodeModal account={account}>
              <Button shape="circle" icon={<QrcodeOutlined />} size="small" />
            </QRCodeModal>
          </Col>
        </Row>
      ) : null}
    </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: Responsive.tsx    From yugong with MIT License 4 votes vote down vote up
Responsive: React.FC<Props> = () => {
  useEffect(() => {
    trackPageView('/首页');
  }, []);
  /**
   * ----------
   * 定义编辑模式
   * ----------
   */
  const { isEditing, auth } = useSelector(
    (state: RootState) => state.controller,
  );

  const history = useHistory();

  const appData = useSelector((state: RootState) => state.appData);
  const activationItem = useSelector(
    (state: RootState) => state.activationItem,
  );
  const stateTag = useSelector((state: RootState) => state.controller.stateTag);

  const forceUpdateByStateTag =
    useDispatch<Dispatch>().controller.forceUpdateByStateTag;
  const setIsEditing = useDispatch<Dispatch>().controller.setIsEditing;
  const updateAppData = useDispatch<Dispatch>().appData.updateAppData;
  const updatePageData = useDispatch<Dispatch>().pageData.updatePage;
  const setWindowHeight = useDispatch<Dispatch>().pageData.setWindowHeight;
  const setWindowWidth = useDispatch<Dispatch>().pageData.setWindowWidth;
  const updateActivationItem =
    useDispatch<Dispatch>().activationItem.updateActivationItem;
  const removeActivationItem =
    useDispatch<Dispatch>().activationItem.removeActivationItem;

  const setRunningTimes = useDispatch<Dispatch>().runningTimes.setRunningTimes;

  const ref = useRef(null);

  const pageData = useSelector((state: RootState) => state.pageData);
  const runningTimes = useSelector((state: RootState) => state.runningTimes);
  const setIsReady = useDispatch<Dispatch>().record.setIsReady;

  const [, setLocalPageData] = useLocalStorage('pageData', null);

  const [showDrawer, setShowDrawer] = useState(false);
  const [showPageDrawer, setShowPageDrawer] = useState(false);
  const [isCreate, setIsCreate] = useState(true);
  const [showTemplateModal, setShowTemplateModal] = useState(false);
  const [hideIframe, sethideIframe] = useState(true);
  const [visibleQrcode, setVisibleQrcode] = useState(false);

  // 创建postmessage通信 usePostMessage收集数据 redux 更新数据
  const sendMessage = usePostMessage(({ tag, value }) => {
    switch (tag) {
      case 'setIsEditing':
        setIsEditing(value);
        break;
      case 'updateAppData':
        updateAppData(value);
        // 同步更新被选模块的属性
        if (activationItem.moduleId === undefined) return;
        const asynAcactivationItem = (value as AppDataListTypes).find(
          (item) => item.moduleId === activationItem.moduleId,
        );
        if (asynAcactivationItem?.moduleId) {
          updateActivationItem(asynAcactivationItem);
        }
        break;
      case 'updateRunningTimes':
        setRunningTimes(value);
        break;
      case 'updatePage':
        updatePageData(value);
        break;
      case 'id':
        // 设置当前项正在被编辑
        // 禁止重复设置当前编辑项
        if (activationItem.moduleId === value) return;
        for (let index = 0; index < appData.length; index++) {
          const element = appData[index];
          if (element.moduleId === value) {
            updateActivationItem({ ...element });
            break;
          }
        }
        setShowDashboard(true);
        break;
      case 'record':
        saveRecord(value)
        break
      default:
        break;
    }
  });

  // 收发处理,子窗口onload时向子窗口发送信息, 通知当前正处于编辑模式下,
  const win: Window | null = ref.current
    ? (ref.current as any).contentWindow
    : null;

  useEffect(() => {
    const windows = (document.getElementById('wrapiframe') as any)
      ?.contentWindow;
    if (windows && !isCreate) {
      windows.onload = () => {
        sendMessage({ tag: 'setIsEditing', value: true }, windows);
        setIsEditing(true);
        setIsReady(true);
        sethideIframe(false);
      };
    }
  }, [sendMessage, setIsEditing, isCreate, setIsReady]);

  useEffect(() => {
    sendMessage({ tag: 'setIsEditing', value: true }, win);
    setIsEditing(true);
  }, [sendMessage, setIsEditing, win]);

  const toggleEdit = useCallback(() => {
    const states = !isEditing;
    sendMessage({ tag: 'setIsEditing', value: states }, win);
    setIsEditing(states);
  }, [isEditing, sendMessage, setIsEditing, win]);

  const toggleCreate = useCallback(() => {
    setIsCreate(!isCreate);
  }, [isCreate]);

  // 收发处理,编辑完数据后通过sendMessage向子窗口发送最新数据。
  useEffect(() => {
    sendMessage(
      {
        tag: 'updateAppData',
        value: appData,
      },
      win,
    );
  }, [sendMessage, win, appData]);

  const onChangeRule = (
    width: number,
    height: number = window.innerHeight - 140,
  ) => {
    setWindowWidth(width);
    setWindowHeight(height);
    const optPageData = { ...pageData };
    optPageData.windowWidth = width;
    optPageData.windowHeight = height;
    setLocalPageData(optPageData);
    if (win) {
      sendMessage({ tag: 'updatePage', value: true }, win);
      sendMessage({ tag: 'setIsEditing', value: isEditing }, win);
    }
    setIsEditing(true);
    forceUpdateByStateTag();
  };

  const [showDashboard, setShowDashboard] = useState(false);
  const [opacity, setOpacity] = useState('1');
  // 无激活模块时隐藏设置面板
  useEffect(() => {
    if (!activationItem.moduleId) {
      setShowDashboard(false);
    }
  }, [activationItem]);

  const hideDashboard = useCallback(() => {
    setShowDashboard(false);
    removeActivationItem();
    if (win) {
      sendMessage({ tag: 'removeActivationItem', value: undefined }, win);
    }
  }, [removeActivationItem, sendMessage, win]);

  const updateProject = useCallback(
    (data: Template) => {
      data.id = pageData.template?.id;
      return updateTemplate(data);
    },
    [pageData],
  );

  interface TemplateAll extends Template {
    pageData: string;
    appData: string;
  }

  // 保存或更新项目
  const onSaveProject = useCallback(
    async ({
      cove = [],
      terminal,
      isPublic,
      describe,
      tag,
      title,
      id,
    }: TemplateInfo) => {
      if (!auth?.isLogin) {
        history.push('/login');
        return;
      }

      // copy
      const pageDataCopy = cloneDeep(pageData);

      // template数据
      const templateData: Template = {
        title: title || pageData.pageTitle,
        terminal,
        cove: cove[0]?.thumbUrl,
        describe,
        tag: tag?.join(','),
        isPublic: isPublic === true ? 1 : 0,
      };
      // 存入模板信息到pageData
      if (!pageDataCopy.template) {
        pageDataCopy.template = templateData;
      }

      // 完整数据
      /**
       * 完整数据包含页面数据、组件数据与模板信息三个部分,
       * 页面数据同时也包含一份模板信息供页面处理
       */
      const params: TemplateAll = {
        pageData: JSON.stringify(pageData),
        appData: JSON.stringify(appData),
        id,
        userId: auth.session?.id,
        ...templateData,
      };
      try {
        loading.show();
        // 更新
        if (!!pageData.template?.id) {
          await updateProject(params);
        } else {
          // 新增
          const newId = await createTemplate(params);
          pageDataCopy.template.id = newId;
        }
        message.success('已发布');
        // 更新
        updatePageData(pageDataCopy);
        // 关闭弹窗
        setShowTemplateModal(false);
        // todo 展示二维码与模板访问链接,支持扫码访问
        setVisibleQrcode(true);
        loading.hide();
      } catch (error) {
        console.error(error);
        loading.hide();
      }
      
    },
    [
      appData,
      auth?.isLogin,
      auth?.session?.id,
      history,
      pageData,
      updatePageData,
      updateProject,
    ],
  );

  const showPublishModal = useCallback(() => {
    if (!auth?.isLogin) {
      history.push('/login');
    }
    setShowTemplateModal(true);
  }, [auth?.isLogin, history]);

  const pageSearch = stringify({ tpl: pageData.template?.id, ...runningTimes.search });

  const codeViewUrl = `${process.env.REACT_APP_SITE_PATH || ''}${pageSearch ? `?${pageSearch}` : ''}`;

  const viewUrl = `${process.env.REACT_APP_SITE_PATH || ''}${window.location.search || '?isediting'
    }`


  return (
    <>
      {isCreate ? (
        <CreateProject goBack={() => toggleCreate()} />
      ) : (
        <div className={s.main}>
          {showDashboard && isEditing ? (
            <Draggable
              axis="both"
              handle={`.${s.header}`}
              onDrag={() => setOpacity('0.5')}
              onStop={() => setOpacity('1')}
            >
              <div className={s.dashboard} style={{ opacity }}>
                <div className={s.header}>
                  <h3>设置面板</h3>
                  <CloseOutlined className={s.icon} onClick={hideDashboard} />
                </div>
                <MiniDashboard />
              </div>
            </Draggable>
          ) : null}
          <div className={s.topmenu}>
            <div className={s.create}>
              <Button
                type="primary"
                onClick={toggleCreate}
                icon={<FileAddOutlined />}
              />
              &nbsp;
              {!isEditing ? (
                <Button
                  type="default"
                  className={s.toggle}
                  onClick={toggleEdit}
                  icon={<EditOutlined />}
                />
              ) : null}
              {isEditing ? (
                <Button
                  type="default"
                  className={s.toggle}
                  onClick={toggleEdit}
                  icon={<EyeOutlined />}
                />
              ) : null}
              &nbsp;
              <Button
                type="default"
                icon={<SettingOutlined />}
                onClick={() => setShowPageDrawer(true)}
              >
                页面
              </Button>
              &nbsp;
              <Button
                type="default"
                icon={<PlusOutlined />}
                onClick={() => setShowDrawer(true)}
              >
                组件
              </Button>
              
              <Undo />
              &nbsp;
              <a href="https://github.com/eightfeet/yugong">
                <Button type="default" icon={<GithubOutlined />}>
                  github
                </Button>
              </a>
            </div>
            <div className={s.save}>
              <Button
                type="primary"
                icon={<CloudUploadOutlined />}
                onClick={showPublishModal}
              >
                {pageData.template?.id ? '修改' : '发布'}
              </Button>
              {pageData.template?.id ? <>
                &nbsp;
                <Button
                  icon={<QrcodeOutlined />}
                  onClick={() => setVisibleQrcode(true)}
                />
              </> : null}

            </div>
          </div>
          <Ruler onChange={onChangeRule} />
          <Drawer
            className={s.drawer}
            title="页面设置"
            width={580}
            onClose={() => setShowPageDrawer(false)}
            visible={showPageDrawer}
            bodyStyle={{ padding: '0', overflow: 'auto' }}
            maskStyle={{ backgroundColor: 'transparent' }}
            footer={null}
          >
            {showPageDrawer ? <PageSetting /> : null}
          </Drawer>
          <Drawer
            className={s.drawer}
            title="组件库"
            width={580}
            onClose={() => setShowDrawer(false)}
            visible={showDrawer}
            bodyStyle={{ padding: '0px' }}
            maskStyle={{ backgroundColor: 'transparent' }}
            footer={null}
          >
            <Repository />
          </Drawer>
          <div className={s.box}>
            <div
              className={classNames({
                [s.viewbg]: !isEditing,
              })}
              style={{ transition: 'all 0.5s' }}
            />
            {!stateTag ? (
              <div
                className={s.iframebox}
                style={{
                  width:
                    pageData.windowWidth === -1
                      ? `100%`
                      : `${pageData.windowWidth}px`,
                  height: `${pageData.windowHeight}px`,
                }}
              >
                <LoadingAnimate />
                <iframe
                  ref={ref}
                  id="wrapiframe"
                  title="wrapiframe"
                  src={viewUrl}
                  style={{
                    border: 'none',
                    opacity: hideIframe ? 0 : 1,
                    minWidth: '100%',
                    minHeight: `${pageData.windowHeight}px`,
                  }}
                />
              </div>
            ) : null}
          </div>
        </div>
      )}
      <TemplateInfoModal
        visible={showTemplateModal}
        onOk={onSaveProject}
        onCancel={() => setShowTemplateModal(false)}
      />
      <QrcodeModal
        visible={visibleQrcode}
        onCancel={() => setVisibleQrcode(false)}
        sourceData={codeViewUrl}
        title="请扫码访问"
        info={<div className={s.viewurl}>访问地址:<a href={codeViewUrl} target={'_blank'} rel="noreferrer">{codeViewUrl}</a></div>}
        options={{
          width: 122,
          margin: 1
        }}
      />
    </>
  );
}
Example #4
Source File: TemplateList.tsx    From yugong with MIT License 4 votes vote down vote up
TemplateList: React.FC<Props> = ({ onSelectedTemplate }) => {
  const { auth } = useSelector((state: RootState) => state.controller);
  const history = useHistory();
  const [templateList, setTemplateList] = useState<queryTemplateParams[]>([]);
  const [templateParams, setTemplateParams] = useState<queryTemplateParams>({
    isPublic: 1,
    limit: 8,
    offset: 0,
  });
  // 总条数决定页数
  const [total, setTotal] = useState<number>();
  const runningTimes = useSelector((state: RootState) => state.runningTimes);
  // 当前页
  const [current, setCurrent] = useState(1)
  const [visibleQrcode, setVisibleQrcode] = useState(0);
  const [tags, setTags] = useState<queryTagParams[]>([]);

  const getTags = useCallback(async () => {
    try {
      loading.show();
      const tagsResult = await queryTag();
      setTags(tagsResult);
      loading.hide();
    } catch (error) {
      loading.hide();
      console.error(error);
    }

  }, []);

  useEffect(() => {
    getTags();
  }, [getTags]);

  const renderTags = useCallback(
    (tag: string) => {
      const tagTsx = tag
        .split(",")
        .filter((item) => Number(item))
        .map((el, ind) => (
          <React.Fragment key={ind}>
            {tags.map((one, index) =>
              Number(el) === one.id ? <Tag key={index}>{one.name}</Tag> : null
            )}
          </React.Fragment>
        ));
      return tagTsx;
    },
    [tags]
  );

  /**
   * 获取列表
   * @param type
   */
  const getTemplateList = useCallback(
    async (query?: queryTemplateParams, force?: boolean) => {
      let params = {
        ...templateParams,
        ...query,
      };
      params = clearEmptyOfObject(params)
      if (force) {
        params = { ...query }
      }
      if (params.isPublic === 0) {
        params.userId = auth?.session?.id
      }
      try {
        loading.show();
        const { rows = [], limit, offset, count } = await queryTemplate(params);
        setTemplateList(rows);
        setTotal(Math.ceil(count / limit) * limit);
        setCurrent(offset / limit + 1);
        loading.hide();
      } catch (error) {
        loading.hide();
        console.error(error);
      }

    },
    [auth?.session?.id, templateParams]
  );

  useEffect(() => {
    getTemplateList({ isPublic: 1 });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const del = useCallback(
    (id) => {
      loading.show();
      deleteTemplate(id).then(() => {
        loading.hide();
        getTemplateList();
      }).catch(error => {
        console.error(error)
        loading.hide();
      });
    },
    [getTemplateList]
  );

  const onChangeTab = useCallback(
    (key) => {
      // 拦截到登录
      if (key === "0" && !auth?.isLogin) {
        history.push("/login");
        return;
      }
      setTemplateParams({
        limit: templateParams.limit,
        offset: 0,
        isPublic: Number(key) as 1 | 0,
      });

      getTemplateList({
        limit: templateParams.limit,
        offset: 0,
        isPublic: Number(key) as 1 | 0,
      }, true)
    },
    [auth?.isLogin, getTemplateList, history, templateParams]
  );

  const onSearch = useCallback(
    (data) => {
      const optData = { ...templateParams, ...data };
      if (!data.tag) {
        delete optData.tag;
      }
      if (!data.title) {
        delete optData.title;
      }
      if (!data.terminal) {
        delete optData.terminal;
      }
      setTemplateParams(optData)
      getTemplateList(optData, true);
    },
    [getTemplateList, templateParams]
  );

  const onDelete = useCallback(
    (id) => () => {
      confirm({
        content: <div>确定要删除当前模板?</div>,
        okText: "确定",
        cancelText: "取消",
        onCancel: () => { },
        onOk: () => del(id),
      });
    },
    [del]
  );

  const onChangePagination = useCallback(
    (page) => {
      const currentOffset = (page - 1) * (templateParams.limit || 0);

      getTemplateList({
        offset: currentOffset
      });
    },
    [getTemplateList, templateParams.limit]
  );

  const handleShowQrCode = useCallback(
    (item) => {
      setVisibleQrcode(item.id);
    },
    [],
  )
  
  const pageSearch = stringify({ tpl: visibleQrcode, ...runningTimes.search });

  const codeViewUrl = `${process.env.REACT_APP_SITE_PATH || ''}${pageSearch ? `?${pageSearch}` : ''}`;

  return (
    <>
      <Tabs className={s.tab} defaultActiveKey="1" onChange={onChangeTab}>
        <TabPane tab="公共模板" key="1"></TabPane>
        <TabPane tab="我的项目" key="0"></TabPane>
      </Tabs>
      <Searchbar key={templateParams.isPublic} onClick={onSearch} tags={tags} />
      <div className={s.container}>
        {templateList.map((item: any, index) => (
          <Card
            hoverable
            className={s.card}
            bodyStyle={{ padding: "10px" }}
            key={`${item.id}${index}`}
            onDoubleClick={() => onSelectedTemplate(item.id, "create")}
            cover={
              <div className={classNames(s.projectcove, s.projectcovetpl)}>
                {item.cove ? (
                  <img src={item.cove} alt={item.title} />
                ) : (
                  <EmptyIcon />
                )}
              </div>
            }
          >
            <Meta
              title={
                <>
                  <h4 className={s.tpltitle}>{item.title}</h4>
                  <div className={s.tpldescript}>{item.describe}</div>
                </>
              }
              description={
                <>
                  <div className={s.tag}>{renderTags(item.tag)}</div>
                  <div className={s.buttonbar}>
                    <Button
                      size="small"
                      type="primary"
                      onClick={() => onSelectedTemplate(item.id, "create")}
                    >
                      从模板创建
                    </Button>
                    {auth?.session?.id === item.userId ? (
                      <>
                        &nbsp;
                        <Button
                          size="small"
                          icon={<EditOutlined />}
                          onClick={() => onSelectedTemplate(item.id, "edit")}
                        />
                        &nbsp;
                        <Button
                          size="small"
                          icon={<DeleteOutlined />}
                          onClick={onDelete(item.id)}
                        />
                      </>
                    ) : null}
                    &nbsp;
                    <Button
                      size="small"
                      icon={<QrcodeOutlined />}
                      onClick={() => handleShowQrCode(item)}
                    />
                  </div>
                </>
              }
            />
          </Card>
        ))}
      </div>
      {!!total && (
        <Pagination
          current={current}
          pageSize={templateParams?.limit || 0}
          onChange={onChangePagination}
          total={total}
        />
      )}
      <QrcodeModal
        visible={!!visibleQrcode}
        onCancel={() => setVisibleQrcode(0)}
        sourceData={codeViewUrl}
        title="请扫码访问"
        info={<div className={s.viewurl}>访问地址:<a href={codeViewUrl} target={'_blank'} rel="noreferrer">{codeViewUrl}</a></div>}
        options={{
          width: 122,
          margin: 1
        }}
      />
    </>
  );
}
Example #5
Source File: index.tsx    From dashboard with Apache License 2.0 4 votes vote down vote up
Welcome: React.FC<WelcomeProps> = (props) => {
  const {currentStaffAdmin, collapsed} = props;
  const [isSmallScreen, setIsSmallScreen] = useState(false);
  const [showSidebar, setShowSidebar] = useState(false);
  const [mainWidth, setMainWidth] = useState(window.innerWidth);
  const [summary, setSummary] = useState<SummaryResult>();
  const [trendItems, setTrendItems] = useState<TrendItem[]>([]);
  const formRef = useRef<FormInstance>();
  const chartRef = useRef<ChartRefConfig>();
  const [allStaffs, setAllStaffs] = useState<StaffOption[]>([]);
  const initialValues = {
    statistic_type: 'total',
    date_range_type: 'week',
    date_range: [moment().add(-7, 'd'), moment()],
    ext_staff_ids: [],
  };

  useEffect(() => {
    const chartWidth = mainWidth - 36 - 4 - (showSidebar ? 300 : 0);
    // @ts-ignore
    chartRef?.current?.chart?.changeSize(chartWidth, 335);
  }, [mainWidth, showSidebar, collapsed]);

  const chartConfig: AreaConfig = {
    data: trendItems,
    // @ts-ignore
    chartRef,
    height: 360,
    xField: 'date',
    yField: 'number',
    meta: {
      date: {
        alias: '日期',
      },
      number: {
        alias: '客户数',
      },
    },
    yAxis: {
      grid: {
        line: {
          style: {
            stroke: 'rgba(0,0,0,0.15)',
            lineWidth: 1,
            lineDash: [4, 5],
          },
        },
      },
    },
    line: {
      style: {
        stroke: 'rgb(91,143,249)',
        lineWidth: 2,
      },
    },
    smooth: true,
    point: {
      size: 2,
    },
    tooltip: {
      domStyles: {
        'g2-tooltip': {
          backgroundColor: 'rgba(0,0,0,0.8)',
        },
        'g2-tooltip-title': {
          color: 'rgb(255,255,255)',
        },
        'g2-tooltip-list': {
          color: 'rgb(255,255,255)',
        },
      },
    },
    areaStyle: function areaStyle() {
      return {fill: 'l(270) 0:#ffffff 0.5:#c0d4fc 1:#5e91f9'};
    },
  };

  const formDataTransform = (params: any): GetTrendParams => {
    const values = {
      ...params,
      start_time: params.date_range[0].format('YYYY-MM-DD').toString(),
      end_time: params.date_range[1].format('YYYY-MM-DD').toString(),
    };
    delete values.date_range_type;
    delete values.date_range;
    return values;
  };

  useEffect(() => {
    QuerySimpleStaffs({page_size: 5000}).then((res) => {
      if (res.code === 0) {
        setAllStaffs(
          res?.data?.items?.map((item: SimpleStaffInterface) => {
            return {
              label: item.name,
              value: item.ext_id,
              ...item,
            };
          }) || [],
        );
      } else {
        message.error(res.message);
      }
    });

    GetTrend(formDataTransform(initialValues)).then((res) => {
      if (res.code === 0) {
        setTrendItems(res?.data || [],
        );
      } else {
        message.error(res.message);
      }
    });

    GetSummary().then((res: CommonResp) => {
      if (res.code !== 0) {
        message.error('获取统计数据失败');
        return;
      }
      setSummary(res.data);
    }).catch((err) => {
      console.log('err', err);
      message.error('获取统计数据失败');
    });

  }, []);

  return (
    <>
      <RcResizeObserver
        key='resize-observer'
        onResize={(offset) => {
          setMainWidth(offset.width);
          setIsSmallScreen(offset.width <= 576);
          setShowSidebar(offset.width >= 992);
        }}
      >
        <ProCard direction={'column'} ghost={true} gutter={8} className={styles.welcomeContainer}>
          <ProCard.Group ghost={true} wrap={!showSidebar} gutter={8} direction={isSmallScreen ? 'column' : 'row'}>
            <ProCard ghost={true} wrap={!showSidebar} gutter={8} direction={isSmallScreen ? 'column' : 'row'}>
              <ProCard ghost={true}>
                <StatisticCard.Group
                  title={
                    <>
                      客户统计
                      <Divider type={'vertical'}/>
                      <a className={styles.detailButton} onClick={() => {
                        history.push('/staff-admin/customer-management/customer');
                      }}>查看客户</a>
                    </>
                  }
                  direction={isSmallScreen ? 'column' : 'row'}
                >
                  <StatisticCard
                    statistic={{
                      title: '客户总数',
                      value: summary?.total_customers_num,
                    }}
                  />
                  <ProCard.Divider type={isSmallScreen ? 'horizontal' : 'vertical'}/>
                  <StatisticCard
                    statistic={{
                      title: '今日新增',
                      value: summary?.today_customers_increase,
                    }}
                  />
                  <ProCard.Divider type={isSmallScreen ? 'horizontal' : 'vertical'}/>
                  <StatisticCard
                    statistic={{
                      title: '今日流失',
                      value: summary?.today_customers_decrease,
                    }}
                  />
                </StatisticCard.Group>
              </ProCard>
              <ProCard ghost={true}>
                <StatisticCard.Group
                  title={
                    <>
                      群统计
                      <Divider type={'vertical'}/>
                      <a className={styles.detailButton} onClick={() => {
                        history.push('/staff-admin/group-chat/list');
                      }}>查看客户群</a>
                    </>
                  }
                  direction={isSmallScreen ? 'column' : 'row'}
                >
                  <StatisticCard
                    statistic={{
                      title: '群总数',
                      value: summary?.total_groups_num,
                    }}
                  />
                  <ProCard.Divider type={isSmallScreen ? 'horizontal' : 'vertical'}/>
                  <StatisticCard
                    colSpan={'8'}
                    statistic={{
                      title: '今日入群',
                      value: summary?.today_groups_increase,
                    }}
                  />
                  <ProCard.Divider type={isSmallScreen ? 'horizontal' : 'vertical'}/>
                  <StatisticCard
                    statistic={{
                      title: '今日退群',
                      value: summary?.today_groups_decrease,
                    }}
                  />
                </StatisticCard.Group>
              </ProCard>
            </ProCard>

            <ProCard hidden={!showSidebar} colSpan={{
              lg: '300px',
            }}>
              <div className={styles.staffInfoBox}>
                <img
                  src={currentStaffAdmin?.avatar_url}
                  className={styles.avatar}
                  alt={currentStaffAdmin?.name}
                />
                <div className={styles.textGroup}>
                  <p className={styles.nickname}>
                    {currentStaffAdmin?.name}
                  </p>
                  <p className={styles.role}>{currentStaffAdmin?.role?.name}</p>
                </div>
              </div>
              <div>
                <Typography.Paragraph style={{marginBottom: 6}}>
                  <Typography.Text style={{color: '#6b7a88'}}>企业名称:</Typography.Text>
                  <Typography.Text>成都小橘科技有限公司</Typography.Text>
                </Typography.Paragraph>
                <Typography.Paragraph style={{marginBottom: 0}}>
                  <Typography.Text style={{color: '#6b7a88'}}>员工总数:</Typography.Text>
                  <Typography.Text>12</Typography.Text>
                </Typography.Paragraph>
              </div>
            </ProCard>
          </ProCard.Group>

          <ProCard.Group ghost={true} gutter={8} style={{marginTop: 12}}>
            <ProCard className={styles.trendChartContainer}>
              <div>
                <Form
                  // @ts-ignore
                  ref={formRef}
                  initialValues={initialValues}
                  onValuesChange={(changedValues, values) => {
                    const transformedValues = {...values};
                    if (changedValues?.date_range_type) {
                      let date_range = [
                        moment(),
                        moment(),
                      ];
                      if (transformedValues.date_range_type === 'week') {
                        date_range = [
                          moment().add(-7, 'd'),
                          moment(),
                        ];
                      }
                      if (transformedValues.date_range_type === 'month') {
                        date_range = [
                          moment().add(-30, 'd'),
                          moment(),
                        ];
                      }

                      formRef.current?.setFieldsValue({
                        date_range,
                      });

                      transformedValues.date_range = date_range;
                    }

                    const hide = message.loading('加载走势数据');
                    GetTrend(formDataTransform(transformedValues)).then((res) => {
                      hide();
                      if (res.code === 0) {
                        setTrendItems(res?.data || [],
                        );
                      } else {
                        message.error(res.message);
                      }
                    }).catch((err) => {
                      console.log('err', err);
                      message.error('走势数据数据加载失败');
                    });
                  }}
                >
                  <div>
                    <Form.Item
                      name='statistic_type'
                    >
                      <Radio.Group>
                        <Radio.Button value='total'>客户总数</Radio.Button>
                        <Radio.Button value='increase'>新增客户数</Radio.Button>
                        <Radio.Button value='decrease'>流失客户数</Radio.Button>
                        <Radio.Button value='net_increase'>净增客户数</Radio.Button>
                      </Radio.Group>
                    </Form.Item>
                  </div>

                  <div style={{display: 'flex'}}>
                    <div className={styles.formItemGroup}>
                      <Form.Item
                        name='date_range_type'
                        className={styles.formItem}
                      >
                        <Select
                          style={{width: 100}}
                        >
                          <Select.Option value='day'>今日</Select.Option>
                          <Select.Option value='week'>近一周</Select.Option>
                          <Select.Option value='month'>近一个月</Select.Option>
                        </Select>
                      </Form.Item>

                      <Form.Item
                        name='date_range'
                        label={'时段'}
                        className={styles.formItem}
                      >
                        <DatePicker.RangePicker/>
                      </Form.Item>

                      <Form.Item
                        name='ext_staff_ids'
                        label={'员工'}
                        style={{width: 300}}
                        className={styles.formItem}
                      >
                        <StaffTreeSelect options={allStaffs} maxTagCount={1}/>
                      </Form.Item>

                    </div>
                    <div>
                      <Button type='default' onClick={() => {
                        formRef.current?.resetFields();
                      }}>
                        重置
                      </Button>
                    </div>
                  </div>

                </Form>

                <Area {...chartConfig} className={styles.chartBox}/>
              </div>
            </ProCard>

            <ProCard.Group hidden={!showSidebar} colSpan={'300px'} style={{padding: '0 4px'}} ghost={true}
                           direction={'column'}>
              <ProCard title={<h4 style={{fontSize: 15}}>OpenSCRM开源私域流量管理系统</h4>} bordered={true}
                       bodyStyle={{paddingTop: 10}}>
                <Row gutter={2}>
                  <Col span={12}>
                    <img src={QrcodeImage} width={100} style={{marginBottom: 12}}/>
                  </Col>
                  <Col span={12}>
                    <div style={{display: 'flex', flexWrap: 'wrap', justifyContent: 'center'}}>
                      <Paragraph type={'secondary'}>
                        遇到任何问题,欢迎联系我们
                      </Paragraph>
                      <Paragraph type={'secondary'} style={{marginBottom: 0}}>
                        微信扫码立即进入交流社群
                      </Paragraph>
                    </div>
                  </Col>
                </Row>
              </ProCard>

              <ProCard title={'消息存档'} bordered={true} style={{marginTop: 8}} bodyStyle={{paddingTop: 12}}>
                <Row gutter={2}>
                  <Col span={12}>
                    <img width={100} src={ChatImage} onClick={() => {
                      history.push('/staff-admin/corp-risk-control/chat-session');
                    }}/>
                  </Col>
                  <Col span={12}>
                    <div style={{display: 'flex', flexWrap: 'wrap', justifyContent: 'end'}}>
                      <Paragraph type={'secondary'}>轻松了解员工和客户的沟通过程</Paragraph>
                      <Button type={'primary'} onClick={() => {
                        history.push('/staff-admin/corp-risk-control/chat-session');
                      }}>立即使用</Button>
                    </div>
                  </Col>
                </Row>
              </ProCard>

              <ProCard title={'入门指引'} bordered={true} style={{marginTop: 8}} bodyStyle={{paddingTop: 10}}>
                <div className={styles.guideContainer}>
                  <div className={styles.item}>
                    文档中心 <Button size={'small'} target={'_blank'} href={'https://docs.openscrm.cn/'}
                                 type={'dashed'}>查看</Button>
                  </div>
                </div>
              </ProCard>

            </ProCard.Group>
          </ProCard.Group>

          <ProCard.Group ghost={true} gutter={8} style={{marginTop: 12}}>
            <ProCard title={'常用功能'} bordered={true} bodyStyle={{paddingTop: 6}}>
              <div className={styles.quickLinkContainer}>

                <a className={styles.item} onClick={() => {
                  history.push('/staff-admin/customer-growth/contact-way')
                }}>
                  <div className={styles.icon}>
                    {getIcon(<QrcodeOutlined style={{color: 'rgba(0,0,0,0.65)'}}/>)}
                  </div>
                  <div className={styles.textGroup}>
                    <p className={styles.title}>渠道活码</p>
                    <p className={styles.desc}>精准运营不同渠道来源的客户</p>
                  </div>
                </a>

                <a className={styles.item} onClick={() => {
                  history.push('/staff-admin/customer-conversion/customer-mass-msg')
                }}>
                  <div className={styles.icon}>
                    {getIcon('icon-fasong')}
                  </div>
                  <div className={styles.textGroup}>
                    <p className={styles.title}>客户群发</p>
                    <p className={styles.desc}>强大的定向群发,最小打扰,最优效果</p>
                  </div>
                </a>

                <a className={styles.item} onClick={() => {
                  history.push('/staff-admin/corp-risk-control/chat-session')
                }}>
                  <div className={styles.icon}>
                    {getIcon(<MessageOutlined style={{color: 'rgba(0,0,0,0.65)'}} />)}
                  </div>
                  <div className={styles.textGroup}>
                    <p className={styles.title}>消息存档</p>
                    <p className={styles.desc}>轻松了解员工和客户的沟通过程</p>
                  </div>
                </a>

                <a className={styles.item} onClick={() => {
                  history.push('/staff-admin/customer-management/customer-tag')
                }}>
                  <div className={styles.icon}>
                    {getIcon(<TagsOutlined style={{color: 'rgba(0,0,0,0.65)'}} />)}
                  </div>
                  <div className={styles.textGroup}>
                    <p className={styles.title}>客户标签</p>
                    <p className={styles.desc}>集中高效管理客户标签,支撑私域精准运营</p>
                  </div>
                </a>

              </div>
            </ProCard>

          </ProCard.Group>


        </ProCard>

      </RcResizeObserver>

    </>
  );
}