diff --git a/react-ui/src/components/ArrayTableCell/index.tsx b/react-ui/src/components/ArrayTableCell/index.tsx deleted file mode 100644 index de109ff4..00000000 --- a/react-ui/src/components/ArrayTableCell/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * @Author: 赵伟 - * @Date: 2024-04-28 14:18:11 - * @Description: 自定义 Table 数组类单元格 - */ - -import { Tooltip } from 'antd'; - -function ArrayTableCell(ellipsis: boolean = false, property?: string) { - return (value?: any | null) => { - if ( - value === undefined || - value === null || - Array.isArray(value) === false || - value.length === 0 - ) { - return --; - } - - let list = value; - if (property && typeof value[0] === 'object') { - list = value.map((item) => item[property]); - } - const text = list.join(','); - if (ellipsis) { - return ( - - {text}; - - ); - } else { - return {text}; - } - }; -} - -export default ArrayTableCell; diff --git a/react-ui/src/components/Footer/index.tsx b/react-ui/src/components/Footer/index.tsx deleted file mode 100644 index 03ac1468..00000000 --- a/react-ui/src/components/Footer/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { GithubOutlined } from '@ant-design/icons'; -import { DefaultFooter } from '@ant-design/pro-components'; -import { useIntl } from '@umijs/max'; -import React from 'react'; - -const Footer: React.FC = () => { - const intl = useIntl(); - const defaultMessage = intl.formatMessage({ - id: 'app.copyright.produced', - defaultMessage: '蚂蚁集团体验技术部出品', - }); - - const currentYear = new Date().getFullYear(); - - return ( - , - href: 'https://github.com/ant-design/ant-design-pro', - blankTarget: true, - }, - { - key: 'Ant Design', - title: 'Ant Design', - href: 'https://ant.design', - blankTarget: true, - }, - ]} - /> - ); -}; - -export default Footer; diff --git a/react-ui/src/components/IconSelector/Category.tsx b/react-ui/src/components/IconSelector/Category.tsx deleted file mode 100644 index 5f683276..00000000 --- a/react-ui/src/components/IconSelector/Category.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useIntl } from '@umijs/max'; -import * as React from 'react'; -import CopyableIcon from './CopyableIcon'; -import type { CategoriesKeys } from './fields'; -import type { ThemeType } from './index'; -import styles from './style.less'; - -interface CategoryProps { - title: CategoriesKeys; - icons: string[]; - theme: ThemeType; - newIcons: string[]; - onSelect: (type: string, name: string) => any; -} - -const Category: React.FC = (props) => { - const { icons, title, newIcons, theme } = props; - const intl = useIntl(); - const [justCopied, setJustCopied] = React.useState(null); - const copyId = React.useRef(null); - const onSelect = React.useCallback((type: string, text: string) => { - const { onSelect } = props; - if (onSelect) { - onSelect(type, text); - } - setJustCopied(type); - copyId.current = setTimeout(() => { - setJustCopied(null); - }, 2000); - }, []); - React.useEffect( - () => () => { - if (copyId.current) { - clearTimeout(copyId.current); - } - }, - [], - ); - - return ( -
-

- {intl.formatMessage({ - id: `app.docs.components.icon.category.${title}`, - defaultMessage: '信息', - })} -

-
    - {icons.map((name) => ( - - ))} -
-
- ); -}; - -export default Category; diff --git a/react-ui/src/components/IconSelector/CopyableIcon.tsx b/react-ui/src/components/IconSelector/CopyableIcon.tsx deleted file mode 100644 index 3440e548..00000000 --- a/react-ui/src/components/IconSelector/CopyableIcon.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as AntdIcons from '@ant-design/icons'; -import { Tooltip } from 'antd'; -import classNames from 'classnames'; -import * as React from 'react'; -import type { ThemeType } from './index'; -import styles from './style.less'; - -const allIcons: { - [key: string]: any; -} = AntdIcons; - -export interface CopyableIconProps { - name: string; - isNew: boolean; - theme: ThemeType; - justCopied: string | null; - onSelect: (type: string, text: string) => any; -} - -const CopyableIcon: React.FC = ({ name, justCopied, onSelect, theme }) => { - const className = classNames({ - copied: justCopied === name, - [theme]: !!theme, - }); - return ( -
  • { - if (onSelect) { - onSelect(theme, name); - } - }} - > - - {React.createElement(allIcons[name], { className: styles.anticon })} - - {/* - {name} - */} -
  • - ); -}; - -export default CopyableIcon; diff --git a/react-ui/src/components/IconSelector/IconPicSearcher.tsx b/react-ui/src/components/IconSelector/IconPicSearcher.tsx deleted file mode 100644 index d80311c6..00000000 --- a/react-ui/src/components/IconSelector/IconPicSearcher.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import KFModal from '@/components/KFModal'; -import * as AntdIcons from '@ant-design/icons'; -import { useIntl } from '@umijs/max'; -import { Popover, Progress, Result, Spin, Tooltip, Upload } from 'antd'; -import React, { useCallback, useEffect, useState } from 'react'; -import './style.less'; - -const allIcons: { [key: string]: any } = AntdIcons; - -const { Dragger } = Upload; -interface AntdIconClassifier { - load: () => void; - predict: (imgEl: HTMLImageElement) => void; -} -declare global { - interface Window { - antdIconClassifier: AntdIconClassifier; - } -} - -interface PicSearcherState { - loading: boolean; - modalOpen: boolean; - popoverVisible: boolean; - icons: iconObject[]; - fileList: any[]; - error: boolean; - modelLoaded: boolean; -} - -interface iconObject { - type: string; - score: number; -} - -const PicSearcher: React.FC = () => { - const intl = useIntl(); - const { formatMessage } = intl; - const [state, setState] = useState({ - loading: false, - modalOpen: false, - popoverVisible: false, - icons: [], - fileList: [], - error: false, - modelLoaded: false, - }); - const predict = (imgEl: HTMLImageElement) => { - try { - let icons: any[] = window.antdIconClassifier.predict(imgEl); - if (gtag && icons.length) { - gtag('event', 'icon', { - event_category: 'search-by-image', - event_label: icons[0].className, - }); - } - icons = icons.map((i) => ({ score: i.score, type: i.className.replace(/\s/g, '-') })); - setState((prev) => ({ ...prev, loading: false, error: false, icons })); - } catch { - setState((prev) => ({ ...prev, loading: false, error: true })); - } - }; - // eslint-disable-next-line class-methods-use-this - const toImage = (url: string) => - new Promise((resolve) => { - const img = new Image(); - img.setAttribute('crossOrigin', 'anonymous'); - img.src = url; - img.onload = () => { - resolve(img); - }; - }); - - const uploadFile = useCallback((file: File) => { - setState((prev) => ({ ...prev, loading: true })); - const reader = new FileReader(); - reader.onload = () => { - toImage(reader.result as string).then(predict); - setState((prev) => ({ - ...prev, - fileList: [{ uid: 1, name: file.name, status: 'done', url: reader.result }], - })); - }; - reader.readAsDataURL(file); - }, []); - - const onPaste = useCallback((event: ClipboardEvent) => { - const items = event.clipboardData && event.clipboardData.items; - let file = null; - if (items && items.length) { - for (let i = 0; i < items.length; i++) { - if (items[i].type.includes('image')) { - file = items[i].getAsFile(); - break; - } - } - } - if (file) { - uploadFile(file); - } - }, []); - const toggleModal = useCallback(() => { - setState((prev) => ({ - ...prev, - modalOpen: !prev.modalOpen, - popoverVisible: false, - fileList: [], - icons: [], - })); - if (!localStorage.getItem('disableIconTip')) { - localStorage.setItem('disableIconTip', 'true'); - } - }, []); - - useEffect(() => { - const script = document.createElement('script'); - script.onload = async () => { - await window.antdIconClassifier.load(); - setState((prev) => ({ ...prev, modelLoaded: true })); - document.addEventListener('paste', onPaste); - }; - script.src = 'https://cdn.jsdelivr.net/gh/lewis617/antd-icon-classifier@0.0/dist/main.js'; - document.head.appendChild(script); - setState((prev) => ({ ...prev, popoverVisible: !localStorage.getItem('disableIconTip') })); - return () => { - document.removeEventListener('paste', onPaste); - }; - }, []); - - return ( -
    - - - - - {state.modelLoaded || ( - -
    - - )} - {state.modelLoaded && ( - uploadFile(o.file as File)} - fileList={state.fileList} - showUploadList={{ showPreviewIcon: false, showRemoveIcon: false }} - > -

    - -

    -

    - {formatMessage({ id: 'app.docs.components.icon.pic-searcher.upload-text' })} -

    -

    - {formatMessage({ id: 'app.docs.components.icon.pic-searcher.upload-hint' })} -

    -
    - )} - -
    - {state.icons.length > 0 && ( -
    - {formatMessage({ id: 'app.docs.components.icon.pic-searcher.result-tip' })} -
    - )} - - {state.icons.length > 0 && ( - - - - - - - )} - - {state.icons.map((icon) => { - const { type } = icon; - const iconName = `${type - .split('-') - .map((str) => `${str[0].toUpperCase()}${str.slice(1)}`) - .join('')}Outlined`; - return ( - - - - - ); - })} - -
    - {formatMessage({ id: 'app.docs.components.icon.pic-searcher.th-icon' })} - - {formatMessage({ id: 'app.docs.components.icon.pic-searcher.th-score' })} -
    - - {React.createElement(allIcons[iconName])} - - - -
    - {state.error && ( - - )} -
    -
    - -
    - ); -}; - -export default PicSearcher; diff --git a/react-ui/src/components/IconSelector/fields.ts b/react-ui/src/components/IconSelector/fields.ts deleted file mode 100644 index 5de572cb..00000000 --- a/react-ui/src/components/IconSelector/fields.ts +++ /dev/null @@ -1,223 +0,0 @@ -import * as AntdIcons from '@ant-design/icons/lib/icons'; - -const all = Object.keys(AntdIcons) - .map((n) => n.replace(/(Outlined|Filled|TwoTone)$/, '')) - .filter((n, i, arr) => arr.indexOf(n) === i); - -const direction = [ - 'StepBackward', - 'StepForward', - 'FastBackward', - 'FastForward', - 'Shrink', - 'ArrowsAlt', - 'Down', - 'Up', - 'Left', - 'Right', - 'CaretUp', - 'CaretDown', - 'CaretLeft', - 'CaretRight', - 'UpCircle', - 'DownCircle', - 'LeftCircle', - 'RightCircle', - 'DoubleRight', - 'DoubleLeft', - 'VerticalLeft', - 'VerticalRight', - 'VerticalAlignTop', - 'VerticalAlignMiddle', - 'VerticalAlignBottom', - 'Forward', - 'Backward', - 'Rollback', - 'Enter', - 'Retweet', - 'Swap', - 'SwapLeft', - 'SwapRight', - 'ArrowUp', - 'ArrowDown', - 'ArrowLeft', - 'ArrowRight', - 'PlayCircle', - 'UpSquare', - 'DownSquare', - 'LeftSquare', - 'RightSquare', - 'Login', - 'Logout', - 'MenuFold', - 'MenuUnfold', - 'BorderBottom', - 'BorderHorizontal', - 'BorderInner', - 'BorderOuter', - 'BorderLeft', - 'BorderRight', - 'BorderTop', - 'BorderVerticle', - 'PicCenter', - 'PicLeft', - 'PicRight', - 'RadiusBottomleft', - 'RadiusBottomright', - 'RadiusUpleft', - 'RadiusUpright', - 'Fullscreen', - 'FullscreenExit', -]; - -const suggestion = [ - 'Question', - 'QuestionCircle', - 'Plus', - 'PlusCircle', - 'Pause', - 'PauseCircle', - 'Minus', - 'MinusCircle', - 'PlusSquare', - 'MinusSquare', - 'Info', - 'InfoCircle', - 'Exclamation', - 'ExclamationCircle', - 'Close', - 'CloseCircle', - 'CloseSquare', - 'Check', - 'CheckCircle', - 'CheckSquare', - 'ClockCircle', - 'Warning', - 'IssuesClose', - 'Stop', -]; - -const editor = [ - 'Edit', - 'Form', - 'Copy', - 'Scissor', - 'Delete', - 'Snippets', - 'Diff', - 'Highlight', - 'AlignCenter', - 'AlignLeft', - 'AlignRight', - 'BgColors', - 'Bold', - 'Italic', - 'Underline', - 'Strikethrough', - 'Redo', - 'Undo', - 'ZoomIn', - 'ZoomOut', - 'FontColors', - 'FontSize', - 'LineHeight', - 'Dash', - 'SmallDash', - 'SortAscending', - 'SortDescending', - 'Drag', - 'OrderedList', - 'UnorderedList', - 'RadiusSetting', - 'ColumnWidth', - 'ColumnHeight', -]; - -const data = [ - 'AreaChart', - 'PieChart', - 'BarChart', - 'DotChart', - 'LineChart', - 'RadarChart', - 'HeatMap', - 'Fall', - 'Rise', - 'Stock', - 'BoxPlot', - 'Fund', - 'Sliders', -]; - -const logo = [ - 'Android', - 'Apple', - 'Windows', - 'Ie', - 'Chrome', - 'Github', - 'Aliwangwang', - 'Dingding', - 'WeiboSquare', - 'WeiboCircle', - 'TaobaoCircle', - 'Html5', - 'Weibo', - 'Twitter', - 'Wechat', - 'Youtube', - 'AlipayCircle', - 'Taobao', - 'Skype', - 'Qq', - 'MediumWorkmark', - 'Gitlab', - 'Medium', - 'Linkedin', - 'GooglePlus', - 'Dropbox', - 'Facebook', - 'Codepen', - 'CodeSandbox', - 'CodeSandboxCircle', - 'Amazon', - 'Google', - 'CodepenCircle', - 'Alipay', - 'AntDesign', - 'AntCloud', - 'Aliyun', - 'Zhihu', - 'Slack', - 'SlackSquare', - 'Behance', - 'BehanceSquare', - 'Dribbble', - 'DribbbleSquare', - 'Instagram', - 'Yuque', - 'Alibaba', - 'Yahoo', - 'Reddit', - 'Sketch', - 'WhatsApp', - 'Dingtalk', -]; - -const datum = [...direction, ...suggestion, ...editor, ...data, ...logo]; - -const other = all.filter((n) => !datum.includes(n)); - -export const categories = { - direction, - suggestion, - editor, - data, - logo, - other, -}; - -export default categories; - -export type Categories = typeof categories; -export type CategoriesKeys = keyof Categories; diff --git a/react-ui/src/components/IconSelector/index.tsx b/react-ui/src/components/IconSelector/index.tsx deleted file mode 100644 index 0d50db68..00000000 --- a/react-ui/src/components/IconSelector/index.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import Icon, * as AntdIcons from '@ant-design/icons'; -import { Empty, Input, Radio } from 'antd'; -import type { RadioChangeEvent } from 'antd/es/radio/interface'; -import debounce from 'lodash/debounce'; -import * as React from 'react'; -import Category from './Category'; -import IconPicSearcher from './IconPicSearcher'; -import type { CategoriesKeys } from './fields'; -import { categories } from './fields'; -import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons'; -// import { useIntl } from '@umijs/max'; - -export enum ThemeType { - Filled = 'Filled', - Outlined = 'Outlined', - TwoTone = 'TwoTone', -} - -const allIcons: { [key: string]: any } = AntdIcons; - -interface IconSelectorProps { - //intl: any; - onSelect: any; -} - -interface IconSelectorState { - theme: ThemeType; - searchKey: string; -} - -const IconSelector: React.FC = (props) => { - // const intl = useIntl(); - // const { messages } = intl; - const { onSelect } = props; - const [displayState, setDisplayState] = React.useState({ - theme: ThemeType.Outlined, - searchKey: '', - }); - - const newIconNames: string[] = []; - - const handleSearchIcon = React.useCallback( - debounce((searchKey: string) => { - setDisplayState((prevState) => ({ ...prevState, searchKey })); - }), - [], - ); - - const handleChangeTheme = React.useCallback((e: RadioChangeEvent) => { - setDisplayState((prevState) => ({ ...prevState, theme: e.target.value as ThemeType })); - }, []); - - const renderCategories = React.useMemo(() => { - const { searchKey = '', theme } = displayState; - - const categoriesResult = Object.keys(categories) - .map((key: CategoriesKeys) => { - let iconList = categories[key]; - if (searchKey) { - const matchKey = searchKey - // eslint-disable-next-line prefer-regex-literals - .replace(new RegExp(`^<([a-zA-Z]*)\\s/>$`, 'gi'), (_, name) => name) - .replace(/(Filled|Outlined|TwoTone)$/, '') - .toLowerCase(); - iconList = iconList.filter((iconName: string) => - iconName.toLowerCase().includes(matchKey), - ); - } - - // CopyrightCircle is same as Copyright, don't show it - iconList = iconList.filter((icon: string) => icon !== 'CopyrightCircle'); - - return { - category: key, - icons: iconList - .map((iconName: string) => iconName + theme) - .filter((iconName: string) => allIcons[iconName]), - }; - }) - .filter(({ icons }) => !!icons.length) - .map(({ category, icons }) => ( - { - if (onSelect) { - onSelect(name, allIcons[name]); - } - }} - /> - )); - return categoriesResult.length === 0 ? : categoriesResult; - }, [displayState.searchKey, displayState.theme]); - return ( - <> -
    - , - value: ThemeType.Outlined, - }, - { - label: , - value: ThemeType.Filled, - }, - { - label: , - value: ThemeType.TwoTone, - }, - ]} - > - {/* - {messages['app.docs.components.icon.outlined']} - - - {messages['app.docs.components.icon.filled']} - - - {messages['app.docs.components.icon.two-tone']} - */} - - handleSearchIcon(e.currentTarget.value)} - size="large" - autoFocus - suffix={} - /> -
    - {renderCategories} - - ); -}; - -export default IconSelector; diff --git a/react-ui/src/components/IconSelector/style.less b/react-ui/src/components/IconSelector/style.less deleted file mode 100644 index 0a4353d6..00000000 --- a/react-ui/src/components/IconSelector/style.less +++ /dev/null @@ -1,137 +0,0 @@ -.iconPicSearcher { - display: inline-block; - margin: 0 8px; - - .icon-pic-btn { - color: @text-color-secondary; - cursor: pointer; - transition: all 0.3s; - - &:hover { - color: @input-icon-hover-color; - } - } -} - -.icon-pic-preview { - width: 30px; - height: 30px; - margin-top: 10px; - padding: 8px; - text-align: center; - border: 1px solid @border-color-base; - border-radius: 4px; - - > img { - max-width: 50px; - max-height: 50px; - } -} - -.icon-pic-search-result { - min-height: 50px; - padding: 0 10px; - - > .result-tip { - padding: 10px 0; - color: @text-color-secondary; - } - - > table { - width: 100%; - - .col-icon { - width: 80px; - padding: 10px 0; - - > .anticon { - font-size: 30px; - - :hover { - color: @link-hover-color; - } - } - } - } -} - -ul.anticonsList { - margin: 2px 0; - overflow: hidden; - direction: ltr; - list-style: none; - - li { - position: relative; - float: left; - width: 48px; - height: 48px; - margin: 3px 0; - padding: 2px 0 0; - overflow: hidden; - color: #555; - text-align: center; - list-style: none; - background-color: inherit; - border-radius: 4px; - cursor: pointer; - transition: color 0.3s ease-in-out, background-color 0.3s ease-in-out; - - .rtl & { - margin: 3px 0; - padding: 2px 0 0; - } - - .anticon { - margin: 4px 0 2px; - font-size: 24px; - transition: transform 0.3s ease-in-out; - will-change: transform; - } - - .anticonClass { - display: block; - font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - white-space: nowrap; - text-align: center; - transform: scale(0.83); - - .ant-badge { - transition: color 0.3s ease-in-out; - } - } - - &:hover { - color: #fff; - background-color: @primary-color; - - .anticon { - transform: scale(1.4); - } - - .ant-badge { - color: #fff; - } - } - - &.TwoTone:hover { - background-color: #8ecafe; - } - - &.copied:hover { - color: rgba(255, 255, 255, 0.2); - } - - &.copied::after { - top: -2px; - opacity: 1; - } - } -} - -.copied-code { - padding: 2px 4px; - font-size: 12px; - background: #f5f5f5; - border-radius: 2px; -} diff --git a/react-ui/src/components/IconSelector/themeIcons.tsx b/react-ui/src/components/IconSelector/themeIcons.tsx deleted file mode 100644 index 1d9762cd..00000000 --- a/react-ui/src/components/IconSelector/themeIcons.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; - -export const FilledIcon: React.FC = (props) => { - const path = - 'M864 64H160C107 64 64 107 64 160v' + - '704c0 53 43 96 96 96h704c53 0 96-43 96-96V16' + - '0c0-53-43-96-96-96z'; - return ( - - - - ); -}; - -export const OutlinedIcon: React.FC = (props) => { - const path = - 'M864 64H160C107 64 64 107 64 160v7' + - '04c0 53 43 96 96 96h704c53 0 96-43 96-96V160c' + - '0-53-43-96-96-96z m-12 800H172c-6.6 0-12-5.4-' + - '12-12V172c0-6.6 5.4-12 12-12h680c6.6 0 12 5.4' + - ' 12 12v680c0 6.6-5.4 12-12 12z'; - return ( - - - - ); -}; - -export const TwoToneIcon: React.FC = (props) => { - const path = - 'M16 512c0 273.932 222.066 496 496 49' + - '6s496-222.068 496-496S785.932 16 512 16 16 238.' + - '066 16 512z m496 368V144c203.41 0 368 164.622 3' + - '68 368 0 203.41-164.622 368-368 368z'; - return ( - - - - ); -}; diff --git a/react-ui/src/components/KFConfirmModal/index.less b/react-ui/src/components/KFConfirmModal/index.less deleted file mode 100644 index 5c82b5ec..00000000 --- a/react-ui/src/components/KFConfirmModal/index.less +++ /dev/null @@ -1,7 +0,0 @@ -.kf-confirm-modal { - &__content { - width: 100%; - font-size: 18px; - text-align: center; - } -} diff --git a/react-ui/src/components/KFConfirmModal/index.tsx b/react-ui/src/components/KFConfirmModal/index.tsx deleted file mode 100644 index d494ad2a..00000000 --- a/react-ui/src/components/KFConfirmModal/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * @Author: 赵伟 - * @Date: 2024-10-10 10:54:25 - * @Description: 自定义 Confirm Modal - */ - -import classNames from 'classnames'; -import KFModal, { KFModalProps } from '../KFModal'; -import './index.less'; - -export interface KFConfirmModalProps extends KFModalProps { - content: string; -} -function KFConfirmModal({ - title, - image, - className = '', - centered, - maskClosable, - content, - ...rest -}: KFConfirmModalProps) { - return ( - -
    {content}
    -
    - ); -} - -export default KFConfirmModal;