diff --git a/src/renderer/src/assets/css/pages/tools/index.scss b/src/renderer/src/assets/css/pages/tools/index.scss index 48a169f..db8f1a9 100644 --- a/src/renderer/src/assets/css/pages/tools/index.scss +++ b/src/renderer/src/assets/css/pages/tools/index.scss @@ -5,66 +5,104 @@ .root-content { padding: 20px; gap: 20px; - flex-wrap: wrap; - justify-content: flex-start; - > .card-box { - width: 180px; - height: 290px; - flex: 0 0 auto; - } + .own-content { + gap: 20px; + flex-wrap: wrap; + justify-content: flex-start; - - & > :first-child { - cursor: pointer; - - .info { - padding-top: 50px; - } - } - - & > :not(:first-child) { - .info { - transform: translateY(40px); - transition: all 0.1s ease; + > .card-box { + width: 180px; + height: 290px; + flex: 0 0 auto; } - .operation { - display: flex; - flex: 1; - justify-content: center; - padding-bottom: 20px; - gap: 4px; - width: 70%; - flex-direction: column; - align-items: center; - visibility: hidden; - opacity: 0; - > *, .edit > * { - width: 100%; + & > :first-child { + cursor: pointer; + + .info { + padding-top: 50px; + } + } + + & > :not(:first-child) { + .info { + transform: translateY(40px); + transition: all 0.1s ease; } - .edit { - > * { - > :first-child { - flex: 1; + .operation { + display: flex; + flex: 1; + justify-content: center; + padding-bottom: 20px; + gap: 4px; + width: 70%; + flex-direction: column; + align-items: center; + visibility: hidden; + opacity: 0; + + > *, .edit > * { + width: 100%; + } + + .edit { + > * { + > :first-child { + flex: 1; + } } } } } + + & > :not(:first-child):hover { + .info { + transform: translateY(-10px); + transition: all 0.2s ease; + } + + .operation { + visibility: visible; + opacity: 1; + transition: all 0.4s ease; + } + } } - & > :not(:first-child):hover { - .info { - transform: translateY(-10px); - transition: all 0.2s ease; + .favorite-divider { + display: flex; + flex-direction: row; + align-items: center; + gap: 20px; + + :first-child, :last-child { + height: 0; + border: { + width: 1px; + color: constants.$divide-color; + style: dashed; + }; } - .operation { - visibility: visible; - opacity: 1; - transition: all 0.4s ease; + .divider-text { + flex: 0 0 auto; + font-size: 1.2em; + color: constants.$font-secondary-color; + } + } + + .star-content { + gap: 20px; + flex-wrap: wrap; + justify-content: flex-start; + + > .card-box { + width: 180px; + height: 290px; + flex: 0 0 auto; } } } diff --git a/src/renderer/src/components/tools/StoreCard.tsx b/src/renderer/src/components/tools/StoreCard.tsx index b305ee3..43f32da 100644 --- a/src/renderer/src/components/tools/StoreCard.tsx +++ b/src/renderer/src/components/tools/StoreCard.tsx @@ -9,6 +9,7 @@ import { navigateToSource, navigateToStore, navigateToView } from '@/util/naviga import { r_tool_add_favorite, r_tool_remove_favorite } from '@/services/tool' import Card from '@/components/common/Card' import FlexBox from '@/components/common/FlexBox' +import { getUserId } from '@/util/auth.tsx' interface StoreCardProps extends DetailedHTMLProps, HTMLDivElement> { icon: ReactNode @@ -16,9 +17,8 @@ interface StoreCardProps extends DetailedHTMLProps(null) const [favorite_, setFavorite_] = useState(favorite) + const [userId, setUserId] = useState('') useEffect(() => { cardRef.current && VanillaTilt.init(cardRef.current, options) + getUserId().then((value) => setUserId(value)) }, [options]) const handleCardOnClick = () => { @@ -72,7 +73,7 @@ const StoreCard = ({ content: ( 请使用手机端扫描上方二维码 @@ -81,24 +82,24 @@ const StoreCard = ({ }) return } - navigateToView(navigate, authorUsername, toolId, platform) + navigateToView(navigate, author.username, toolId, platform) } const handleOnClickAuthor = (e: MouseEvent) => { e.stopPropagation() - navigateToStore(navigate, authorUsername) + navigateToStore(navigate, author.username) } const handleOnSourceBtnClick = (e: MouseEvent) => { e.stopPropagation() - navigateToSource(navigate, authorUsername, toolId, platform) + navigateToSource(navigate, author.username, toolId, platform) } const handleOnStarBtnClick = (e: MouseEvent) => { e.stopPropagation() if (favorite_) { void r_tool_remove_favorite({ - username: authorUsername, + authorId: author.id, toolId: toolId, platform: platform }).then((res) => { @@ -111,7 +112,7 @@ const StoreCard = ({ }) } else { void r_tool_add_favorite({ - username: authorUsername, + authorId: author.id, toolId: toolId, platform: platform }).then((res) => { @@ -135,7 +136,7 @@ const StoreCard = ({ content: ( 请使用手机端扫描上方二维码 @@ -149,7 +150,7 @@ const StoreCard = ({ if (!checkDesktop()) { void message.loading({ content: '启动桌面端中……', key: 'LOADING', duration: 0 }) protocolCheck( - `oxygen://openurl/view/${authorUsername}/${toolId}`, + `oxygen://openurl/view/${author.username}/${toolId}`, () => { void message.warning('打开失败,此应用需要桌面端环境,请安装桌面端后重试') void message.destroy('LOADING') @@ -165,12 +166,12 @@ const StoreCard = ({ ) return } - navigateToView(navigate, authorUsername, toolId, platform) + navigateToView(navigate, author.username, toolId, platform) } const handleOnWebBtnClick = (e: MouseEvent) => { e.stopPropagation() - navigateToView(navigate, authorUsername, toolId, platform) + navigateToView(navigate, author.username, toolId, platform) } return ( @@ -194,22 +195,22 @@ const StoreCard = ({
{`ID: ${toolId}`}
{toolDesc &&
{`简介:${toolDesc}`}
} - {authorAvatar && authorName && ( + {showAuthor && (
} style={{ background: COLOR_BACKGROUND }} />
- -
{authorName}
+ +
{author.userInfo.nickname}
)} @@ -238,13 +239,15 @@ const StoreCard = ({ - - - + {author.id !== userId && ( + + + + )}
diff --git a/src/renderer/src/global.d.ts b/src/renderer/src/global.d.ts index b83ec6f..233d760 100644 --- a/src/renderer/src/global.d.ts +++ b/src/renderer/src/global.d.ts @@ -657,7 +657,7 @@ interface ToolStoreGetParam extends PageParam { } interface ToolFavoriteAddRemoveParam { - username: string + authorId: string toolId: string platform: Platform } diff --git a/src/renderer/src/pages/Tools/Store.tsx b/src/renderer/src/pages/Tools/Store.tsx index ac27fc2..f187751 100644 --- a/src/renderer/src/pages/Tools/Store.tsx +++ b/src/renderer/src/pages/Tools/Store.tsx @@ -143,9 +143,7 @@ const Store = () => { toolName={firstTool!.name} toolId={firstTool!.toolId} toolDesc={firstTool!.description} - authorName={firstTool!.author.userInfo.nickname} - authorAvatar={firstTool!.author.userInfo.avatar} - authorUsername={firstTool!.author.username} + author={firstTool!.author} ver={firstTool!.ver} platform={firstTool!.platform} supportPlatform={tools.map((value) => value.platform)} diff --git a/src/renderer/src/pages/Tools/User.tsx b/src/renderer/src/pages/Tools/User.tsx index 369b912..2124196 100644 --- a/src/renderer/src/pages/Tools/User.tsx +++ b/src/renderer/src/pages/Tools/User.tsx @@ -206,7 +206,8 @@ const User = () => { toolName={firstTool!.name} toolId={firstTool!.toolId} toolDesc={firstTool!.description} - authorUsername={firstTool!.author.username} + author={firstTool!.author} + showAuthor={false} ver={firstTool!.ver} platform={firstTool!.platform} supportPlatform={tools.map((value) => value.platform)} diff --git a/src/renderer/src/pages/Tools/index.tsx b/src/renderer/src/pages/Tools/index.tsx index cd5ec46..95526da 100644 --- a/src/renderer/src/pages/Tools/index.tsx +++ b/src/renderer/src/pages/Tools/index.tsx @@ -19,6 +19,7 @@ import { r_tool_cancel, r_tool_delete, r_tool_get, + r_tool_get_favorite, r_tool_submit, r_tool_upgrade } from '@/services/tool' @@ -27,6 +28,7 @@ import HideScrollbar from '@/components/common/HideScrollbar' import FlexBox from '@/components/common/FlexBox' import RepositoryCard from '@/components/tools/RepositoryCard' import LoadMoreCard from '@/components/tools/LoadMoreCard' +import StoreCard from '@/components/tools/StoreCard.tsx' interface ToolCardProps { tools: ToolVo[] @@ -208,6 +210,9 @@ const Tools = () => { const [hasNextPage, setHasNextPage] = useState(false) const [toolData, setToolData] = useState([]) const [upgradeForm] = AntdForm.useForm() + const [currentStarPage, setCurrentStarPage] = useState(0) + const [hasNextStarPage, setHasNextStarPage] = useState(false) + const [starToolData, setStarToolData] = useState([]) const handleOnDeleteTool = (tool: ToolVo) => { modal @@ -436,6 +441,13 @@ const Tools = () => { getTool(currentPage + 1) } + const handleOnLoadMoreStar = () => { + if (loading) { + return + } + getStarTool(currentStarPage + 1) + } + const getTool = (page: number) => { if (loading) { return @@ -468,6 +480,47 @@ const Tools = () => { void message.error('获取工具失败,请稍后重试') } }) + .finally(() => { + setLoading(false) + message.destroy('LOADING') + if (currentStarPage === 0) { + getStarTool(1) + } + }) + } + + const getStarTool = (page: number) => { + if (loading) { + return + } + setLoading(true) + void message.loading({ content: '加载收藏列表中', key: 'LOADING', duration: 0 }) + + void r_tool_get_favorite({ currentPage: page }) + .then((res) => { + const response = res.data + + switch (response.code) { + case DATABASE_SELECT_SUCCESS: + setCurrentStarPage(response.data!.current) + if ( + response.data!.current === response.data!.pages || + response.data!.total === 0 + ) { + setHasNextStarPage(false) + } else { + setHasNextStarPage(true) + } + if (response.data!.current === 1) { + setStarToolData(response.data!.records) + } else { + setStarToolData([...starToolData, ...response.data!.records]) + } + break + default: + void message.error('加载失败,请稍后重试') + } + }) .finally(() => { setLoading(false) message.destroy('LOADING') @@ -485,30 +538,91 @@ const Tools = () => { <> - - } - toolName={'创建工具'} - url={'/create'} - /> - {toolData && - Object.values( - toolData.reduce((result: Record, item) => { - result[item.toolId] = result[item.toolId] || [] - result[item.toolId].push(item) - return result - }, {}) - ).map((value) => ( - - ))} - {hasNextPage && } + + + } + toolName={'创建工具'} + url={'/create'} + /> + {toolData && + Object.values( + toolData.reduce((result: Record, item) => { + result[item.toolId] = result[item.toolId] || [] + result[item.toolId].push(item) + return result + }, {}) + ).map((value) => ( + + ))} + {hasNextPage && } + + +
+
收藏
+
+ + + {starToolData + ?.reduce((previousValue: ToolVo[], currentValue) => { + if ( + !previousValue.some( + (value) => + value.author.id === currentValue.author.id && + value.toolId === currentValue.toolId + ) + ) { + previousValue.push(currentValue) + } + return previousValue + }, []) + .map((item) => { + const tools = starToolData.filter( + (value) => + value.author.id === item.author.id && + value.toolId === item.toolId + ) + const webTool = tools.find((value) => value.platform === 'WEB') + const desktopTool = tools.find( + (value) => value.platform === 'DESKTOP' + ) + const androidTool = tools.find( + (value) => value.platform === 'ANDROID' + ) + const firstTool = + (checkDesktop() + ? desktopTool || webTool + : webTool || desktopTool) || androidTool + + return ( + + } + toolName={firstTool!.name} + toolId={firstTool!.toolId} + toolDesc={firstTool!.description} + author={firstTool!.author} + ver={firstTool!.ver} + platform={firstTool!.platform} + supportPlatform={tools.map((value) => value.platform)} + favorite={firstTool!.favorite} + /> + ) + })} + {hasNextStarPage && } + diff --git a/src/renderer/src/services/tool.tsx b/src/renderer/src/services/tool.tsx index b462f37..2a31952 100644 --- a/src/renderer/src/services/tool.tsx +++ b/src/renderer/src/services/tool.tsx @@ -40,7 +40,10 @@ export const r_tool_store_get_by_username = (username: string, param: ToolStoreG request.get>(`${URL_TOOL_STORE}/${username}`, param) export const r_tool_add_favorite = (param: ToolFavoriteAddRemoveParam) => - request.post(`${URL_TOOL_FAVORITE}`, param) + request.post(URL_TOOL_FAVORITE, param) export const r_tool_remove_favorite = (param: ToolFavoriteAddRemoveParam) => - request.delete(`${URL_TOOL_FAVORITE}`, param) + request.delete(URL_TOOL_FAVORITE, param) + +export const r_tool_get_favorite = (param: PageParam) => + request.get>(URL_TOOL_FAVORITE, param)