diff --git a/src/renderer/src/assets/css/components/system/setting-card.scss b/src/renderer/src/assets/css/components/system/setting-card.scss new file mode 100644 index 0000000..4703dc8 --- /dev/null +++ b/src/renderer/src/assets/css/components/system/setting-card.scss @@ -0,0 +1,33 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-setting-card] { + .settings-card { + padding: 20px; + gap: 20px; + color: constants.$main-color; + + > .head { + align-items: center; + gap: 5px; + + .icon { + font-size: constants.$SIZE_ICON_MD; + flex: 0 0 auto; + } + + .title { + display: flex; + font-size: 1.2em; + } + + :nth-child(n+3) { + flex: 0 0 auto; + color: constants.$font-main-color; + } + + .bt-save { + color: constants.$main-color; + } + } + } +} diff --git a/src/renderer/src/assets/css/components/system/statistics-card.scss b/src/renderer/src/assets/css/components/system/statistics-card.scss new file mode 100644 index 0000000..600a45f --- /dev/null +++ b/src/renderer/src/assets/css/components/system/statistics-card.scss @@ -0,0 +1,78 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-statistics-card] { + .statistics-card { + padding: 20px; + gap: 20px; + + > .head { + align-items: center; + gap: 5px; + color: constants.$main-color; + + .icon { + font-size: constants.$SIZE_ICON_MD; + flex: 0 0 auto; + } + + .title { + display: flex; + font-size: 1.2em; + } + + :nth-child(n+3) { + flex: 0 0 auto; + color: constants.$font-main-color; + } + } + + .card-content { + font-size: 1.1em; + padding: 0 10px; + gap: 10px; + + .key, .value-percent { + flex: 0 0 auto; + color: constants.$font-main-color; + } + + .value { + color: constants.$font-secondary-color; + overflow: hidden; + + > * { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + .value-chart { + justify-content: space-around; + width: 0; + + > div { + max-height: 12px; + height: 12px; + + > * { + transform: translateY(1px); + } + } + } + + .value-percent { + text-align: right; + } + + .big-chart { + width: 0; + height: 400px; + } + + > * { + gap: 5px; + } + } + } +} diff --git a/src/renderer/src/assets/css/components/system/system-card.scss b/src/renderer/src/assets/css/components/system/system-card.scss new file mode 100644 index 0000000..9c12029 --- /dev/null +++ b/src/renderer/src/assets/css/components/system/system-card.scss @@ -0,0 +1,28 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-system-card] { + cursor: pointer; + + .system-card { + width: 100%; + height: 100%; + margin-top: 100px; + text-align: center; + gap: 42px; + + > * { + flex: 0 0 auto; + display: block; + } + + .icon { + color: constants.$production-color; + font-size: constants.$SIZE_ICON_XL; + } + + .text { + font-weight: bolder; + font-size: 2em; + } + } +} diff --git a/src/renderer/src/assets/css/components/tools/load-more-card.scss b/src/renderer/src/assets/css/components/tools/load-more-card.scss new file mode 100644 index 0000000..aa3d7ab --- /dev/null +++ b/src/renderer/src/assets/css/components/tools/load-more-card.scss @@ -0,0 +1,27 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-load-more-card] { + cursor: pointer; + + .load-more-card { + width: 100%; + height: 100%; + text-align: center; + align-items: center; + + .icon { + display: flex; + font-size: constants.$SIZE_ICON_XXL; + color: constants.$production-color; + align-items: center; + transform: translateY(-20px); + } + + .text { + position: absolute; + top: 60%; + font-size: 1.2em; + font-weight: bolder; + } + } +} diff --git a/src/renderer/src/assets/css/components/tools/repository-card.scss b/src/renderer/src/assets/css/components/tools/repository-card.scss new file mode 100644 index 0000000..06d360e --- /dev/null +++ b/src/renderer/src/assets/css/components/tools/repository-card.scss @@ -0,0 +1,47 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-repository-card] { + .repository-card { + width: 100%; + height: 100%; + text-align: center; + align-items: center; + + > * { + display: block; + flex: 0 0 auto; + } + + .version-select { + position: absolute; + top: 10px; + left: 10px; + width: 9em; + } + + .upgrade-bt { + position: absolute; + top: 10px; + right: 10px; + font-size: 1.8em; + } + + .icon { + display: flex; + padding-top: 50px; + padding-bottom: 20px; + color: constants.$production-color; + font-size: constants.$SIZE_ICON_XL; + justify-content: center; + + img { + width: constants.$SIZE_ICON_XL; + } + } + + .tool-name { + font-weight: bolder; + font-size: 1.6em; + } + } +} diff --git a/src/renderer/src/assets/css/components/tools/store-card.scss b/src/renderer/src/assets/css/components/tools/store-card.scss new file mode 100644 index 0000000..15d0570 --- /dev/null +++ b/src/renderer/src/assets/css/components/tools/store-card.scss @@ -0,0 +1,85 @@ +@use '@/assets/css/constants' as constants; + +[data-component=component-store-card] { + cursor: pointer; + + .store-card { + width: 100%; + height: 100%; + text-align: center; + align-items: center; + + > * { + display: block; + flex: 0 0 auto; + } + + + .icon { + display: flex; + padding-top: 40px; + padding-bottom: 20px; + color: constants.$production-color; + font-size: constants.$SIZE_ICON_XL; + justify-content: center; + + img { + width: constants.$SIZE_ICON_XL; + } + } + + .version { + position: absolute; + left: 10px; + top: 10px; + } + + .info { + padding-top: 20px; + + .tool-name { + font-weight: bolder; + font-size: 1.6em; + } + + .tool-desc { + margin-top: 10px; + color: constants.$font-secondary-color; + } + } + + .author { + display: flex; + margin-top: auto; + flex-direction: row; + justify-content: end; + padding-bottom: 10px; + gap: 10px; + + .avatar { + > * { + width: 24px; + height: 24px; + } + } + + .author-name { + display: flex; + align-items: center; + } + } + + .operation { + display: flex; + position: absolute; + top: 10px; + right: 12px; + font-size: 1.6em; + gap: 4px; + + > *:hover { + color: constants.$font-secondary-color; + } + } + } +} diff --git a/src/renderer/src/assets/css/pages/system/index.scss b/src/renderer/src/assets/css/pages/system/index.scss index f41fad8..6f3f7b6 100644 --- a/src/renderer/src/assets/css/pages/system/index.scss +++ b/src/renderer/src/assets/css/pages/system/index.scss @@ -12,30 +12,6 @@ height: 360px; flex: 0 0 auto; overflow: hidden !important; - cursor: pointer; - - .common-card { - width: 100%; - height: 100%; - margin-top: 100px; - text-align: center; - gap: 42px; - - > * { - flex: 0 0 auto; - display: block; - } - - .icon { - color: constants.$production-color; - font-size: constants.$SIZE_ICON_XL; - } - - .text { - font-weight: bolder; - font-size: 2em; - } - } } } } diff --git a/src/renderer/src/assets/css/pages/system/settings.scss b/src/renderer/src/assets/css/pages/system/settings.scss index 839e7dd..7db4529 100644 --- a/src/renderer/src/assets/css/pages/system/settings.scss +++ b/src/renderer/src/assets/css/pages/system/settings.scss @@ -11,36 +11,6 @@ > * { flex: 0 0 auto; } - - .settings-card { - padding: 20px; - gap: 20px; - color: constants.$main-color; - - > .head { - align-items: center; - gap: 5px; - - .icon { - font-size: constants.$SIZE_ICON_MD; - flex: 0 0 auto; - } - - .title { - display: flex; - font-size: 1.2em; - } - - :nth-child(n+3) { - flex: 0 0 auto; - color: constants.$font-main-color; - } - - .bt-save { - color: constants.$main-color; - } - } - } } } } diff --git a/src/renderer/src/assets/css/pages/system/statistics.scss b/src/renderer/src/assets/css/pages/system/statistics.scss index 8c7230c..40e15a5 100644 --- a/src/renderer/src/assets/css/pages/system/statistics.scss +++ b/src/renderer/src/assets/css/pages/system/statistics.scss @@ -10,81 +10,6 @@ > .card-box { width: 48%; flex: 0 0 auto; - - .common-card { - padding: 20px; - gap: 20px; - - > .head { - align-items: center; - gap: 5px; - color: constants.$main-color; - - .icon { - font-size: constants.$SIZE_ICON_MD; - flex: 0 0 auto; - } - - .title { - display: flex; - font-size: 1.2em; - } - - :nth-child(n+3) { - flex: 0 0 auto; - color: constants.$font-main-color; - } - } - - .card-content { - font-size: 1.1em; - padding: 0 10px; - gap: 10px; - - .key, .value-percent { - flex: 0 0 auto; - color: constants.$font-main-color; - } - - .value { - color: constants.$font-secondary-color; - overflow: hidden; - - > * { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - } - - .value-chart { - justify-content: space-around; - width: 0; - - > div { - max-height: 12px; - height: 12px; - - > * { - transform: translateY(1px); - } - } - } - - .value-percent { - text-align: right; - } - - .big-chart { - width: 0; - height: 400px; - } - - > * { - gap: 5px; - } - } - } } } } diff --git a/src/renderer/src/assets/css/pages/tools/index.scss b/src/renderer/src/assets/css/pages/tools/index.scss index c8df8f6..48a169f 100644 --- a/src/renderer/src/assets/css/pages/tools/index.scss +++ b/src/renderer/src/assets/css/pages/tools/index.scss @@ -12,73 +12,6 @@ width: 180px; height: 290px; flex: 0 0 auto; - - .common-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - - > * { - display: block; - flex: 0 0 auto; - } - - .version-select { - position: absolute; - top: 10px; - left: 10px; - width: 9em; - } - - .upgrade-bt { - position: absolute; - top: 10px; - right: 10px; - font-size: 1.8em; - } - - .icon { - display: flex; - padding-top: 50px; - padding-bottom: 20px; - color: constants.$production-color; - font-size: constants.$SIZE_ICON_XL; - justify-content: center; - - img { - width: constants.$SIZE_ICON_XL; - } - } - - .tool-name { - font-weight: bolder; - font-size: 1.6em; - } - } - - .load-more-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - cursor: pointer; - - .icon { - display: flex; - font-size: constants.$SIZE_ICON_XXL; - color: constants.$production-color; - align-items: center; - transform: translateY(-20px); - } - - .text { - position: absolute; - top: 60%; - font-size: 1.2em; - font-weight: bolder; - } - } } diff --git a/src/renderer/src/assets/css/pages/tools/store.scss b/src/renderer/src/assets/css/pages/tools/store.scss index 3bffda7..b87a3f5 100644 --- a/src/renderer/src/assets/css/pages/tools/store.scss +++ b/src/renderer/src/assets/css/pages/tools/store.scss @@ -30,109 +30,6 @@ width: 180px; height: 290px; flex: 0 0 auto; - cursor: pointer; - - .common-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - - > * { - display: block; - flex: 0 0 auto; - } - - - .icon { - display: flex; - padding-top: 40px; - padding-bottom: 20px; - color: constants.$production-color; - font-size: constants.$SIZE_ICON_XL; - justify-content: center; - - img { - width: constants.$SIZE_ICON_XL; - } - } - - .version { - position: absolute; - left: 10px; - top: 10px; - } - - .info { - padding-top: 20px; - - .tool-name { - font-weight: bolder; - font-size: 1.6em; - } - - .tool-desc { - margin-top: 10px; - color: constants.$font-secondary-color; - } - } - - .author { - display: flex; - margin-top: auto; - flex-direction: row; - justify-content: end; - padding-bottom: 10px; - gap: 10px; - - .avatar { - > * { - width: 24px; - height: 24px; - } - } - - .author-name { - display: flex; - align-items: center; - } - } - - .operation { - display: flex; - position: absolute; - top: 10px; - right: 12px; - font-size: 1.6em; - gap: 4px; - - > *:hover { - color: constants.$font-secondary-color; - } - } - } - - .load-more-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - - .icon { - display: flex; - font-size: constants.$SIZE_ICON_XXL; - color: constants.$production-color; - align-items: center; - transform: translateY(-20px); - } - - .text { - position: absolute; - top: 60%; - font-size: 1.2em; - font-weight: bolder; - } - } } .no-tool { diff --git a/src/renderer/src/assets/css/pages/tools/user.scss b/src/renderer/src/assets/css/pages/tools/user.scss index 05f0cc5..97eb6c0 100644 --- a/src/renderer/src/assets/css/pages/tools/user.scss +++ b/src/renderer/src/assets/css/pages/tools/user.scss @@ -72,109 +72,6 @@ width: 180px; height: 290px; flex: 0 0 auto; - cursor: pointer; - - .common-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - - > * { - display: block; - flex: 0 0 auto; - } - - - .icon { - display: flex; - padding-top: 40px; - padding-bottom: 20px; - color: constants.$production-color; - font-size: constants.$SIZE_ICON_XL; - justify-content: center; - - img { - width: constants.$SIZE_ICON_XL; - } - } - - .version { - position: absolute; - left: 10px; - top: 10px; - } - - .info { - padding-top: 20px; - - .tool-name { - font-weight: bolder; - font-size: 1.6em; - } - - .tool-desc { - margin-top: 10px; - color: constants.$font-secondary-color; - } - } - - .author { - display: flex; - margin-top: auto; - flex-direction: row; - justify-content: end; - padding-bottom: 10px; - gap: 10px; - - .avatar { - > * { - width: 24px; - height: 24px; - } - } - - .author-name { - display: flex; - align-items: center; - } - } - - .operation { - display: flex; - position: absolute; - top: 10px; - right: 12px; - font-size: 1.6em; - gap: 4px; - - > *:hover { - color: constants.$font-secondary-color; - } - } - } - - .load-more-card { - width: 100%; - height: 100%; - text-align: center; - align-items: center; - - .icon { - display: flex; - font-size: constants.$SIZE_ICON_XXL; - color: constants.$production-color; - align-items: center; - transform: translateY(-20px); - } - - .text { - position: absolute; - top: 60%; - font-size: 1.2em; - font-weight: bolder; - } - } } .no-tool { diff --git a/src/renderer/src/components/system/SettingCard.tsx b/src/renderer/src/components/system/SettingCard.tsx new file mode 100644 index 0000000..874efd1 --- /dev/null +++ b/src/renderer/src/components/system/SettingCard.tsx @@ -0,0 +1,48 @@ +import { PropsWithChildren, ReactNode } from 'react' +import Icon from '@ant-design/icons' +import '@/assets/css/components/system/setting-card.scss' +import Card from '@/components/common/Card' +import FlexBox from '@/components/common/FlexBox' +import Permission from '@/components/common/Permission' +import LoadingMask from '@/components/common/LoadingMask' + +interface SettingsCardProps extends PropsWithChildren { + icon: IconComponent + title: string + loading?: boolean + modifyOperationCode?: string[] + expand?: ReactNode + onReset?: () => void + onSave?: () => void +} +export const SettingsCard = (props: SettingsCardProps) => { + return ( + + + + +
{props.title}
+ {!props.loading && ( + + {props.expand} + + + + + + + + )} +
+ } + hidden={!props.loading} + > + {props.children} + +
+
+ ) +} + +export default SettingsCard diff --git a/src/renderer/src/components/system/StatisticsCard.tsx b/src/renderer/src/components/system/StatisticsCard.tsx new file mode 100644 index 0000000..567d6e2 --- /dev/null +++ b/src/renderer/src/components/system/StatisticsCard.tsx @@ -0,0 +1,35 @@ +import { PropsWithChildren, ReactNode } from 'react' +import Icon from '@ant-design/icons' +import '@/assets/css/components/system/statistics-card.scss' +import Card from '@/components/common/Card' +import FlexBox from '@/components/common/FlexBox' +import LoadingMask from '@/components/common/LoadingMask' + +interface StatisticsCardProps extends PropsWithChildren { + icon: IconComponent + title: ReactNode + loading?: boolean + expand?: ReactNode +} + +export const StatisticsCard = (props: StatisticsCardProps) => { + return ( + + + + +
{props.title}
+ {props.expand} +
+ +
+
+ ) +} + +export default StatisticsCard diff --git a/src/renderer/src/components/system/SystemCard.tsx b/src/renderer/src/components/system/SystemCard.tsx new file mode 100644 index 0000000..1afce03 --- /dev/null +++ b/src/renderer/src/components/system/SystemCard.tsx @@ -0,0 +1,62 @@ +import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react' +import Icon from '@ant-design/icons' +import VanillaTilt, { TiltOptions } from 'vanilla-tilt' +import '@/assets/css/components/system/system-card.scss' +import Card from '@/components/common/Card' +import FlexBox from '@/components/common/FlexBox' + +interface SystemCardProps + extends DetailedHTMLProps, HTMLDivElement> { + icon: IconComponent + description?: ReactNode + options?: TiltOptions + url?: string +} + +const SystemCard = forwardRef( + ({ + style, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + ref, + icon, + description, + options = { + reverse: true, + max: 8, + glare: true, + scale: 1.03 + }, + url, + children, + ...props + }) => { + const navigate = useNavigate() + const cardRef = useRef(null) + + useEffect(() => { + cardRef.current && VanillaTilt.init(cardRef.current, options) + }, [options]) + + const handleCardOnClick = () => { + url && navigate(url) + } + + return ( + + + +
{children}
+
{description}
+
+
+ ) + } +) + +export default SystemCard diff --git a/src/renderer/src/components/tools/LoadMoreCard.tsx b/src/renderer/src/components/tools/LoadMoreCard.tsx new file mode 100644 index 0000000..a7c0736 --- /dev/null +++ b/src/renderer/src/components/tools/LoadMoreCard.tsx @@ -0,0 +1,42 @@ +import VanillaTilt from 'vanilla-tilt' +import Icon from '@ant-design/icons' +import '@/assets/css/components/tools/load-more-card.scss' +import FlexBox from '@/components/common/FlexBox' +import Card from '@/components/common/Card' + +interface LoadMoreCardProps { + onClick: () => void +} + +const LoadMoreCard = ({ onClick }: LoadMoreCardProps) => { + const cardRef = useRef(null) + + useEffect(() => { + cardRef.current && + VanillaTilt.init(cardRef.current, { + reverse: true, + max: 8, + glare: true, + ['max-glare']: 0.3, + scale: 1.03 + }) + }, []) + + return ( + + +
+ {' '} +
+
加载更多
+
+
+ ) +} + +export default LoadMoreCard diff --git a/src/renderer/src/components/tools/RepositoryCard.tsx b/src/renderer/src/components/tools/RepositoryCard.tsx new file mode 100644 index 0000000..c00a9d7 --- /dev/null +++ b/src/renderer/src/components/tools/RepositoryCard.tsx @@ -0,0 +1,107 @@ +import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react' +import VanillaTilt, { TiltOptions } from 'vanilla-tilt' +import '@/assets/css/components/tools/repository-card.scss' +import Card from '@/components/common/Card' +import FlexBox from '@/components/common/FlexBox' + +interface RepositoryCardProps + extends DetailedHTMLProps, HTMLDivElement> { + icon: ReactNode + toolName?: string + toolId?: string + options?: TiltOptions + url?: string + onOpen?: () => void + onEdit?: () => void + onSource?: () => void + onPublish?: () => void + onCancelReview?: () => void + onDelete?: () => void +} + +const RepositoryCard = ({ + style, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + ref, + icon, + toolName, + toolId, + options = { + reverse: true, + max: 8, + glare: true, + ['max-glare']: 0.3, + scale: 1.03 + }, + url, + onOpen, + onEdit, + onSource, + onPublish, + onCancelReview, + onDelete, + children, + ...props +}: RepositoryCardProps) => { + const navigate = useNavigate() + const cardRef = useRef(null) + + useEffect(() => { + cardRef.current && VanillaTilt.init(cardRef.current, options) + }, [options]) + + const handleCardOnClick = () => { + url && navigate(url) + } + + return ( + + +
{icon}
+
+ {toolName &&
{toolName}
} + {toolId &&
{`ID: ${toolId}`}
} +
+
+ {onOpen && ( + + 打开 + + )} + {onEdit && onPublish && ( +
+ + 编辑 + 发布 + +
+ )} + {onSource && ( + + 源码 + + )} + {onCancelReview && ( + + 取消审核 + + )} + {onDelete && ( + + 删除 + + )} +
+ {children} +
+
+ ) +} + +export default RepositoryCard diff --git a/src/renderer/src/components/tools/StoreCard.tsx b/src/renderer/src/components/tools/StoreCard.tsx new file mode 100644 index 0000000..b305ee3 --- /dev/null +++ b/src/renderer/src/components/tools/StoreCard.tsx @@ -0,0 +1,256 @@ +import { DetailedHTMLProps, HTMLAttributes, MouseEvent, ReactNode } from 'react' +import VanillaTilt, { TiltOptions } from 'vanilla-tilt' +import protocolCheck from 'custom-protocol-check' +import Icon from '@ant-design/icons' +import '@/assets/css/components/tools/store-card.scss' +import { COLOR_BACKGROUND, COLOR_MAIN, COLOR_PRODUCTION } from '@/constants/common.constants' +import { checkDesktop } from '@/util/common' +import { navigateToSource, navigateToStore, navigateToView } from '@/util/navigation' +import { r_tool_add_favorite, r_tool_remove_favorite } from '@/services/tool' +import Card from '@/components/common/Card' +import FlexBox from '@/components/common/FlexBox' + +interface StoreCardProps extends DetailedHTMLProps, HTMLDivElement> { + icon: ReactNode + toolName: string + toolId: string + toolDesc: string + options?: TiltOptions + authorName?: string + authorAvatar?: string + authorUsername: string + ver: string + platform: Platform + supportPlatform: Platform[] + favorite: boolean +} + +const StoreCard = ({ + style, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + ref, + icon, + toolName, + toolId, + toolDesc, + options = { + reverse: true, + max: 8, + glare: true, + ['max-glare']: 0.3, + scale: 1.03 + }, + authorName, + authorAvatar, + authorUsername, + ver, + platform, + supportPlatform, + favorite, + ...props +}: StoreCardProps) => { + const navigate = useNavigate() + const [modal, contextHolder] = AntdModal.useModal() + const cardRef = useRef(null) + const [favorite_, setFavorite_] = useState(favorite) + + useEffect(() => { + cardRef.current && VanillaTilt.init(cardRef.current, options) + }, [options]) + + const handleCardOnClick = () => { + if (!checkDesktop() && platform === 'DESKTOP') { + void message.warning('此应用需要桌面端环境,请在桌面端打开') + return + } + if (platform === 'ANDROID') { + void modal.info({ + icon: , + title: 'Android 端', + centered: true, + maskClosable: true, + content: ( + + + 请使用手机端扫描上方二维码 + + ) + }) + return + } + navigateToView(navigate, authorUsername, toolId, platform) + } + + const handleOnClickAuthor = (e: MouseEvent) => { + e.stopPropagation() + navigateToStore(navigate, authorUsername) + } + + const handleOnSourceBtnClick = (e: MouseEvent) => { + e.stopPropagation() + navigateToSource(navigate, authorUsername, toolId, platform) + } + + const handleOnStarBtnClick = (e: MouseEvent) => { + e.stopPropagation() + if (favorite_) { + void r_tool_remove_favorite({ + username: authorUsername, + toolId: toolId, + platform: platform + }).then((res) => { + const response = res.data + if (response.success) { + setFavorite_(false) + } else { + void message.error('取消收藏失败,请稍后重试') + } + }) + } else { + void r_tool_add_favorite({ + username: authorUsername, + toolId: toolId, + platform: platform + }).then((res) => { + const response = res.data + if (response.success) { + setFavorite_(true) + } else { + void message.error('收藏失败,请稍后重试') + } + }) + } + } + + const handleOnAndroidBtnClick = (e: MouseEvent) => { + e.stopPropagation() + void modal.info({ + icon: , + title: 'Android 端', + centered: true, + maskClosable: true, + content: ( + + + 请使用手机端扫描上方二维码 + + ) + }) + } + + const handleOnDesktopBtnClick = (e: MouseEvent) => { + e.stopPropagation() + if (!checkDesktop()) { + void message.loading({ content: '启动桌面端中……', key: 'LOADING', duration: 0 }) + protocolCheck( + `oxygen://openurl/view/${authorUsername}/${toolId}`, + () => { + void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') + void message.destroy('LOADING') + }, + () => { + void message.destroy('LOADING') + }, + 2000, + () => { + void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') + void message.destroy('LOADING') + } + ) + return + } + navigateToView(navigate, authorUsername, toolId, platform) + } + + const handleOnWebBtnClick = (e: MouseEvent) => { + e.stopPropagation() + navigateToView(navigate, authorUsername, toolId, platform) + } + + return ( + <> + + +
{icon}
+
+ + {platform.slice(0, 1)}-{ver} + +
+
+
{toolName}
+
{`ID: ${toolId}`}
+ {toolDesc &&
{`简介:${toolDesc}`}
} +
+ {authorAvatar && authorName && ( +
+
+ + } + style={{ background: COLOR_BACKGROUND }} + /> +
+ +
{authorName}
+
+
+ )} +
+ {platform !== 'ANDROID' && supportPlatform.includes('ANDROID') && ( + + + + )} + {platform === 'DESKTOP' && supportPlatform.includes('WEB') && ( + + + + )} + {platform === 'WEB' && supportPlatform.includes('DESKTOP') && ( + + + + )} + + + + + + +
+
+
+ {contextHolder} + + ) +} + +export default StoreCard diff --git a/src/renderer/src/pages/System/Settings/Base.tsx b/src/renderer/src/pages/System/Settings/Base.tsx index d0dd2ee..2f11c1e 100644 --- a/src/renderer/src/pages/System/Settings/Base.tsx +++ b/src/renderer/src/pages/System/Settings/Base.tsx @@ -1,6 +1,6 @@ import { hasPermission } from '@/util/auth' import { r_sys_settings_base_get, r_sys_settings_base_update } from '@/services/system' -import { SettingsCard } from '@/pages/System/Settings' +import SettingsCard from '@/components/system/SettingCard' const Base = () => { const [baseForm] = AntdForm.useForm() diff --git a/src/renderer/src/pages/System/Settings/Mail.tsx b/src/renderer/src/pages/System/Settings/Mail.tsx index 22d0222..205474b 100644 --- a/src/renderer/src/pages/System/Settings/Mail.tsx +++ b/src/renderer/src/pages/System/Settings/Mail.tsx @@ -5,7 +5,7 @@ import { r_sys_settings_mail_send, r_sys_settings_mail_update } from '@/services/system' -import { SettingsCard } from '@/pages/System/Settings' +import SettingsCard from '@/components/system/SettingCard' const Mail = () => { const [modal, contextHolder] = AntdModal.useModal() diff --git a/src/renderer/src/pages/System/Settings/SensitiveWord.tsx b/src/renderer/src/pages/System/Settings/SensitiveWord.tsx index 7b738a3..db80be5 100644 --- a/src/renderer/src/pages/System/Settings/SensitiveWord.tsx +++ b/src/renderer/src/pages/System/Settings/SensitiveWord.tsx @@ -7,7 +7,7 @@ import { r_sys_settings_sensitive_get, r_sys_settings_sensitive_update } from '@/services/system' -import { SettingsCard } from '@/pages/System/Settings' +import SettingsCard from '@/components/system/SettingCard' const SensitiveWord = () => { const [dataSource, setDataSource] = useState() diff --git a/src/renderer/src/pages/System/Settings/TwoFactor.tsx b/src/renderer/src/pages/System/Settings/TwoFactor.tsx index 7d93d61..08f80fd 100644 --- a/src/renderer/src/pages/System/Settings/TwoFactor.tsx +++ b/src/renderer/src/pages/System/Settings/TwoFactor.tsx @@ -1,6 +1,6 @@ import { hasPermission } from '@/util/auth' import { r_sys_settings_two_factor_get, r_sys_settings_two_factor_update } from '@/services/system' -import { SettingsCard } from '@/pages/System/Settings' +import SettingsCard from '@/components/system/SettingCard' const TwoFactor = () => { const [twoFactorForm] = AntdForm.useForm() diff --git a/src/renderer/src/pages/System/Settings/index.tsx b/src/renderer/src/pages/System/Settings/index.tsx index 94cba62..c23cf3b 100644 --- a/src/renderer/src/pages/System/Settings/index.tsx +++ b/src/renderer/src/pages/System/Settings/index.tsx @@ -1,55 +1,12 @@ -import { PropsWithChildren, ReactNode } from 'react' -import Icon from '@ant-design/icons' import '@/assets/css/pages/system/settings.scss' import FitFullscreen from '@/components/common/FitFullscreen' import HideScrollbar from '@/components/common/HideScrollbar' -import Card from '@/components/common/Card' import FlexBox from '@/components/common/FlexBox' -import LoadingMask from '@/components/common/LoadingMask' import Permission from '@/components/common/Permission' import Base from '@/pages/System/Settings/Base' import Mail from '@/pages/System/Settings/Mail' import SensitiveWord from '@/pages/System/Settings/SensitiveWord' -import TwoFactor from '@/pages/System/Settings/TwoFactor.tsx' - -interface SettingsCardProps extends PropsWithChildren { - icon: IconComponent - title: string - loading?: boolean - modifyOperationCode?: string[] - expand?: ReactNode - onReset?: () => void - onSave?: () => void -} -export const SettingsCard = (props: SettingsCardProps) => { - return ( - - - - -
{props.title}
- {!props.loading && ( - - {props.expand} - - - - - - - - )} -
- } - hidden={!props.loading} - > - {props.children} - -
-
- ) -} +import TwoFactor from '@/pages/System/Settings/TwoFactor' const Settings = () => { return ( diff --git a/src/renderer/src/pages/System/Statistics/ActiveInfo.tsx b/src/renderer/src/pages/System/Statistics/ActiveInfo.tsx index 0e93ff6..65f800a 100644 --- a/src/renderer/src/pages/System/Statistics/ActiveInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/ActiveInfo.tsx @@ -4,7 +4,7 @@ import { getTimesBetweenTwoTimes } from '@/util/datetime' import { r_sys_statistics_active } from '@/services/system' import FlexBox from '@/components/common/FlexBox' import { getTooltipTimeFormatter, lineEChartsBaseOption } from '@/pages/System/Statistics/shared' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const ActiveInfo = () => { const activeInfoDivRef = useRef(null) @@ -147,7 +147,7 @@ const ActiveInfo = () => { } return ( - @@ -183,7 +183,7 @@ const ActiveInfo = () => {
- + ) } diff --git a/src/renderer/src/pages/System/Statistics/CPUInfo.tsx b/src/renderer/src/pages/System/Statistics/CPUInfo.tsx index 1d53964..0303f09 100644 --- a/src/renderer/src/pages/System/Statistics/CPUInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/CPUInfo.tsx @@ -7,7 +7,7 @@ import { barEChartsBaseOption, EChartsOption } from '@/pages/System/Statistics/shared' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const CPUInfo = () => { const keyDivRef = useRef(null) @@ -142,7 +142,7 @@ const CPUInfo = () => { return ( <> - { - + ) } diff --git a/src/renderer/src/pages/System/Statistics/HardwareInfo.tsx b/src/renderer/src/pages/System/Statistics/HardwareInfo.tsx index 96399ca..f6f0c9e 100644 --- a/src/renderer/src/pages/System/Statistics/HardwareInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/HardwareInfo.tsx @@ -1,6 +1,6 @@ import { r_sys_statistics_hardware } from '@/services/system' import FlexBox from '@/components/common/FlexBox' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const HardwareInfo = () => { const [hardwareInfoData, setHardwareInfoData] = useState() @@ -17,7 +17,7 @@ const HardwareInfo = () => { }, []) return ( - {
{hardwareInfoData?.disks}
-
+ ) } diff --git a/src/renderer/src/pages/System/Statistics/OnlineInfo.tsx b/src/renderer/src/pages/System/Statistics/OnlineInfo.tsx index 624ceca..3bc5921 100644 --- a/src/renderer/src/pages/System/Statistics/OnlineInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/OnlineInfo.tsx @@ -4,7 +4,7 @@ import { getTimesBetweenTwoTimes } from '@/util/datetime' import { r_sys_statistics_online } from '@/services/system' import FlexBox from '@/components/common/FlexBox' import { getTooltipTimeFormatter, lineEChartsBaseOption } from '@/pages/System/Statistics/shared' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const OnlineInfo = () => { const onlineInfoDivRef = useRef(null) @@ -148,7 +148,7 @@ const OnlineInfo = () => { } return ( - @@ -188,7 +188,7 @@ const OnlineInfo = () => {
- + ) } diff --git a/src/renderer/src/pages/System/Statistics/SoftwareInfo.tsx b/src/renderer/src/pages/System/Statistics/SoftwareInfo.tsx index 65fe84a..a7bf4c5 100644 --- a/src/renderer/src/pages/System/Statistics/SoftwareInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/SoftwareInfo.tsx @@ -1,7 +1,7 @@ import { utcToLocalTime } from '@/util/datetime' import { r_sys_statistics_software } from '@/services/system' import FlexBox from '@/components/common/FlexBox' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const SoftwareInfo = () => { const [softwareInfoData, setSoftwareInfoData] = useState() @@ -18,7 +18,7 @@ const SoftwareInfo = () => { }, []) return ( - {
-
+ ) } diff --git a/src/renderer/src/pages/System/Statistics/StorageInfo.tsx b/src/renderer/src/pages/System/Statistics/StorageInfo.tsx index c68a198..9202234 100644 --- a/src/renderer/src/pages/System/Statistics/StorageInfo.tsx +++ b/src/renderer/src/pages/System/Statistics/StorageInfo.tsx @@ -8,7 +8,7 @@ import { barEChartsBaseOption, EChartsOption } from '@/pages/System/Statistics/shared' -import { CommonCard } from '@/pages/System/Statistics' +import StatisticsCard from '@/components/system/StatisticsCard' const StorageInfo = () => { const keyDivRef = useRef(null) @@ -161,7 +161,7 @@ const StorageInfo = () => { return ( <> - { - + ) } diff --git a/src/renderer/src/pages/System/Statistics/index.tsx b/src/renderer/src/pages/System/Statistics/index.tsx index 04077b2..2e04c84 100644 --- a/src/renderer/src/pages/System/Statistics/index.tsx +++ b/src/renderer/src/pages/System/Statistics/index.tsx @@ -1,11 +1,7 @@ -import { PropsWithChildren, ReactNode } from 'react' -import Icon from '@ant-design/icons' import '@/assets/css/pages/system/statistics.scss' -import Card from '@/components/common/Card' import FlexBox from '@/components/common/FlexBox' import FitFullscreen from '@/components/common/FitFullscreen' import HideScrollbar from '@/components/common/HideScrollbar' -import LoadingMask from '@/components/common/LoadingMask' import Permission from '@/components/common/Permission' import OnlineInfo from '@/pages/System/Statistics/OnlineInfo' import ActiveInfo from '@/pages/System/Statistics/ActiveInfo' @@ -14,33 +10,6 @@ import HardwareInfo from '@/pages/System/Statistics/HardwareInfo' import CPUInfo from '@/pages/System/Statistics/CPUInfo' import StorageInfo from '@/pages/System/Statistics/StorageInfo' -interface CommonCardProps extends PropsWithChildren { - icon: IconComponent - title: ReactNode - loading?: boolean - expand?: ReactNode -} - -export const CommonCard = (props: CommonCardProps) => { - return ( - - - - -
{props.title}
- {props.expand} -
- -
-
- ) -} - const Statistics = () => { return ( <> diff --git a/src/renderer/src/pages/System/index.tsx b/src/renderer/src/pages/System/index.tsx index 57203a0..c194cae 100644 --- a/src/renderer/src/pages/System/index.tsx +++ b/src/renderer/src/pages/System/index.tsx @@ -1,65 +1,9 @@ -import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react' -import Icon from '@ant-design/icons' -import VanillaTilt, { TiltOptions } from 'vanilla-tilt' import '@/assets/css/pages/system/index.scss' import HideScrollbar from '@/components/common/HideScrollbar' import FitFullscreen from '@/components/common/FitFullscreen' import FlexBox from '@/components/common/FlexBox' -import Card from '@/components/common/Card' import Permission from '@/components/common/Permission' - -interface CommonCardProps - extends DetailedHTMLProps, HTMLDivElement> { - icon: IconComponent - description?: ReactNode - options?: TiltOptions - url?: string -} - -const CommonCard = forwardRef( - ({ - style, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, - icon, - description, - options = { - reverse: true, - max: 8, - glare: true, - scale: 1.03 - }, - url, - children, - ...props - }) => { - const navigate = useNavigate() - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && VanillaTilt.init(cardRef.current, options) - }, [options]) - - const handleCardOnClick = () => { - url && navigate(url) - } - - return ( - - - -
{children}
-
{description}
-
-
- ) - } -) +import SystemCard from '@/components/system/SystemCard.tsx' const System = () => { return ( @@ -68,54 +12,54 @@ const System = () => { - + 系统概况 - + - + 系统设置 - + - + 工具管理 - + - + 模板管理 - + - + 基板管理 - + - + 类别管理 - + - + 用户管理 - + - + 角色管理 - + - + 群组管理 - + - + 系统日志 - + diff --git a/src/renderer/src/pages/Tools/Store.tsx b/src/renderer/src/pages/Tools/Store.tsx index 1539c73..ac27fc2 100644 --- a/src/renderer/src/pages/Tools/Store.tsx +++ b/src/renderer/src/pages/Tools/Store.tsx @@ -1,292 +1,13 @@ -import { DetailedHTMLProps, HTMLAttributes, MouseEvent, ReactNode, UIEvent } from 'react' -import VanillaTilt, { TiltOptions } from 'vanilla-tilt' -import protocolCheck from 'custom-protocol-check' -import Icon from '@ant-design/icons' +import { UIEvent } from 'react' import '@/assets/css/pages/tools/store.scss' -import { - COLOR_BACKGROUND, - COLOR_MAIN, - COLOR_PRODUCTION, - DATABASE_SELECT_SUCCESS -} from '@/constants/common.constants' +import { DATABASE_SELECT_SUCCESS } from '@/constants/common.constants' import { checkDesktop } from '@/util/common' -import { navigateToSource, navigateToStore, navigateToView } from '@/util/navigation' -import { r_tool_add_favorite, r_tool_remove_favorite, r_tool_store_get } from '@/services/tool' -import Card from '@/components/common/Card' +import { r_tool_store_get } from '@/services/tool' import FlexBox from '@/components/common/FlexBox' import FitFullscreen from '@/components/common/FitFullscreen' import HideScrollbar from '@/components/common/HideScrollbar' - -interface CommonCardProps - extends DetailedHTMLProps, HTMLDivElement> { - icon: ReactNode - toolName: string - toolId: string - toolDesc: string - options?: TiltOptions - authorName: string - authorAvatar: string - authorUsername: string - ver: string - platform: Platform - supportPlatform: Platform[] - favorite: boolean -} - -const CommonCard = ({ - style, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, - icon, - toolName, - toolId, - toolDesc, - options = { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }, - authorName, - authorAvatar, - authorUsername, - ver, - platform, - supportPlatform, - favorite, - ...props -}: CommonCardProps) => { - const navigate = useNavigate() - const [modal, contextHolder] = AntdModal.useModal() - const cardRef = useRef(null) - const [favorite_, setFavorite_] = useState(favorite) - - useEffect(() => { - cardRef.current && VanillaTilt.init(cardRef.current, options) - }, [options]) - - const handleCardOnClick = () => { - if (!checkDesktop() && platform === 'DESKTOP') { - void message.warning('此应用需要桌面端环境,请在桌面端打开') - return - } - if (platform === 'ANDROID') { - void modal.info({ - icon: , - title: 'Android 端', - centered: true, - maskClosable: true, - content: ( - - - 请使用手机端扫描上方二维码 - - ) - }) - return - } - navigateToView(navigate, authorUsername, toolId, platform) - } - - const handleOnClickAuthor = (e: MouseEvent) => { - e.stopPropagation() - navigateToStore(navigate, authorUsername) - } - - const handleOnSourceBtnClick = (e: MouseEvent) => { - e.stopPropagation() - navigateToSource(navigate, authorUsername, toolId, platform) - } - - const handleOnStarBtnClick = (e: MouseEvent) => { - e.stopPropagation() - if (favorite_) { - void r_tool_remove_favorite({ - username: authorUsername, - toolId: toolId, - platform: platform - }).then((res) => { - const response = res.data - if (response.success) { - setFavorite_(false) - } else { - void message.error('取消收藏失败,请稍后重试') - } - }) - } else { - void r_tool_add_favorite({ - username: authorUsername, - toolId: toolId, - platform: platform - }).then((res) => { - const response = res.data - if (response.success) { - setFavorite_(true) - } else { - void message.error('收藏失败,请稍后重试') - } - }) - } - } - - const handleOnAndroidBtnClick = (e: MouseEvent) => { - e.stopPropagation() - void modal.info({ - icon: , - title: 'Android 端', - centered: true, - maskClosable: true, - content: ( - - - 请使用手机端扫描上方二维码 - - ) - }) - } - - const handleOnDesktopBtnClick = (e: MouseEvent) => { - e.stopPropagation() - if (!checkDesktop()) { - void message.loading({ content: '启动桌面端中……', key: 'LOADING', duration: 0 }) - protocolCheck( - `oxygen://openurl/view/${authorUsername}/${toolId}`, - () => { - void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') - void message.destroy('LOADING') - }, - () => { - void message.destroy('LOADING') - }, - 2000, - () => { - void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') - void message.destroy('LOADING') - } - ) - return - } - navigateToView(navigate, authorUsername, toolId, platform) - } - - const handleOnWebBtnClick = (e: MouseEvent) => { - e.stopPropagation() - navigateToView(navigate, authorUsername, toolId, platform) - } - - return ( - <> - - -
{icon}
-
- - {platform.slice(0, 1)}-{ver} - -
-
-
{toolName}
-
{`ID: ${toolId}`}
- {toolDesc &&
{`简介:${toolDesc}`}
} -
-
-
- - } - style={{ background: COLOR_BACKGROUND }} - /> -
- -
{authorName}
-
-
-
- {platform !== 'ANDROID' && supportPlatform.includes('ANDROID') && ( - - - - )} - {platform === 'DESKTOP' && supportPlatform.includes('WEB') && ( - - - - )} - {platform === 'WEB' && supportPlatform.includes('DESKTOP') && ( - - - - )} - - - - - - -
-
-
- {contextHolder} - - ) -} - -interface LoadMoreCardProps { - onClick: () => void -} - -const LoadMoreCard = ({ onClick }: LoadMoreCardProps) => { - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && - VanillaTilt.init(cardRef.current, { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }) - }, []) - - return ( - - -
- {' '} -
-
加载更多
-
-
- ) -} +import StoreCard from '@/components/tools/StoreCard' +import LoadMoreCard from '@/components/tools/LoadMoreCard' const Store = () => { const scrollTopRef = useRef(0) @@ -411,7 +132,7 @@ const Store = () => { : webTool || desktopTool) || androidTool return ( - , HTMLDivElement> { - icon: ReactNode - toolName: string - toolId: string - toolDesc: string - options?: TiltOptions - authorUsername: string - ver: string - platform: Platform - supportPlatform: Platform[] -} - -const CommonCard = ({ - style, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, - icon, - toolName, - toolId, - toolDesc, - options = { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }, - authorUsername, - ver, - platform, - supportPlatform, - ...props -}: CommonCardProps) => { - const navigate = useNavigate() - const [modal, contextHolder] = AntdModal.useModal() - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && VanillaTilt.init(cardRef.current, options) - }, [options]) - - const handleCardOnClick = () => { - if (!checkDesktop() && platform === 'DESKTOP') { - void message.warning('此应用需要桌面端环境,请在桌面端打开') - return - } - if (platform === 'ANDROID') { - void modal.info({ - icon: , - title: 'Android 端', - centered: true, - maskClosable: true, - content: ( - - - 请使用手机端扫描上方二维码 - - ) - }) - return - } - navigateToView(navigate, authorUsername, toolId, platform) - } - - const handleOnSourceBtnClick = (e: MouseEvent) => { - e.stopPropagation() - navigateToSource(navigate, authorUsername, toolId, platform) - } - - const handleOnAndroidBtnClick = (e: MouseEvent) => { - e.stopPropagation() - void modal.info({ - icon: , - title: 'Android 端', - centered: true, - maskClosable: true, - content: ( - - - 请使用手机端扫描上方二维码 - - ) - }) - } - - const handleOnDesktopBtnClick = (e: MouseEvent) => { - e.stopPropagation() - if (!checkDesktop()) { - void message.loading({ content: '启动桌面端中……', key: 'LOADING', duration: 0 }) - protocolCheck( - `oxygen://openurl/view/${authorUsername}/${toolId}`, - () => { - void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') - void message.destroy('LOADING') - }, - () => { - void message.destroy('LOADING') - }, - 2000, - () => { - void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') - void message.destroy('LOADING') - } - ) - return - } - navigateToView(navigate, authorUsername, toolId, platform) - } - - const handleOnWebBtnClick = (e: MouseEvent) => { - e.stopPropagation() - navigateToView(navigate, authorUsername, toolId, platform) - } - - return ( - <> - - -
{icon}
-
- - {platform.slice(0, 1)}-{ver} - -
-
-
{toolName}
-
{`ID: ${toolId}`}
- {toolDesc &&
{`简介:${toolDesc}`}
} -
-
- {platform !== 'ANDROID' && supportPlatform.includes('ANDROID') && ( - - - - )} - {platform === 'DESKTOP' && supportPlatform.includes('WEB') && ( - - - - )} - {platform === 'WEB' && supportPlatform.includes('DESKTOP') && ( - - - - )} - - - -
-
-
- {contextHolder} - - ) -} - -interface LoadMoreCardProps { - onClick: () => void -} - -const LoadMoreCard = ({ onClick }: LoadMoreCardProps) => { - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && - VanillaTilt.init(cardRef.current, { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }) - }, []) - - return ( - - -
- {' '} -
-
加载更多
-
-
- ) -} +import StoreCard from '@/components/tools/StoreCard' +import LoadMoreCard from '@/components/tools/LoadMoreCard' const User = () => { const { username } = useParams() @@ -401,7 +195,7 @@ const User = () => { : webTool || desktopTool) || androidTool return ( - { ver={firstTool!.ver} platform={firstTool!.platform} supportPlatform={tools.map((value) => value.platform)} + favorite={firstTool!.favorite} /> ) })} diff --git a/src/renderer/src/pages/Tools/index.tsx b/src/renderer/src/pages/Tools/index.tsx index 2733c31..cd5ec46 100644 --- a/src/renderer/src/pages/Tools/index.tsx +++ b/src/renderer/src/pages/Tools/index.tsx @@ -1,6 +1,4 @@ -import { DetailedHTMLProps, HTMLAttributes, ReactNode } from 'react' import Icon from '@ant-design/icons' -import VanillaTilt, { TiltOptions } from 'vanilla-tilt' import '@/assets/css/pages/tools/index.scss' import { DATABASE_DELETE_SUCCESS, @@ -27,106 +25,8 @@ import { import FitFullscreen from '@/components/common/FitFullscreen' import HideScrollbar from '@/components/common/HideScrollbar' import FlexBox from '@/components/common/FlexBox' -import Card from '@/components/common/Card' - -interface CommonCardProps - extends DetailedHTMLProps, HTMLDivElement> { - icon: ReactNode - toolName?: string - toolId?: string - options?: TiltOptions - url?: string - onOpen?: () => void - onEdit?: () => void - onSource?: () => void - onPublish?: () => void - onCancelReview?: () => void - onDelete?: () => void -} - -const CommonCard = ({ - style, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ref, - icon, - toolName, - toolId, - options = { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }, - url, - onOpen, - onEdit, - onSource, - onPublish, - onCancelReview, - onDelete, - children, - ...props -}: CommonCardProps) => { - const navigate = useNavigate() - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && VanillaTilt.init(cardRef.current, options) - }, [options]) - - const handleCardOnClick = () => { - url && navigate(url) - } - - return ( - - -
{icon}
-
- {toolName &&
{toolName}
} - {toolId &&
{`ID: ${toolId}`}
} -
-
- {onOpen && ( - - 打开 - - )} - {onEdit && onPublish && ( -
- - 编辑 - 发布 - -
- )} - {onSource && ( - - 源码 - - )} - {onCancelReview && ( - - 取消审核 - - )} - {onDelete && ( - - 删除 - - )} -
- {children} -
-
- ) -} +import RepositoryCard from '@/components/tools/RepositoryCard' +import LoadMoreCard from '@/components/tools/LoadMoreCard' interface ToolCardProps { tools: ToolVo[] @@ -262,7 +162,7 @@ const ToolCard = ({ tools, onDelete, onUpgrade, onSubmit, onCancel }: ToolCardPr } return ( - } toolName={selectedTool.name} toolId={selectedTool.toolId} @@ -296,37 +196,7 @@ const ToolCard = ({ tools, onDelete, onUpgrade, onSubmit, onCancel }: ToolCardPr /> )} - - ) -} - -interface LoadMoreCardProps { - onClick: () => void -} - -const LoadMoreCard = ({ onClick }: LoadMoreCardProps) => { - const cardRef = useRef(null) - - useEffect(() => { - cardRef.current && - VanillaTilt.init(cardRef.current, { - reverse: true, - max: 8, - glare: true, - ['max-glare']: 0.3, - scale: 1.03 - }) - }, []) - - return ( - - -
- {' '} -
-
加载更多
-
-
+ ) } @@ -616,7 +486,7 @@ const Tools = () => { - } toolName={'创建工具'} url={'/create'}