From 6e78707d9e2d230f7a5c6a13f5910034bed90b87 Mon Sep 17 00:00:00 2001 From: nyne Date: Sun, 25 May 2025 11:27:24 +0800 Subject: [PATCH] Add AboutPage component and integrate sorting options in resource retrieval --- frontend/src/app.tsx | 2 + frontend/src/i18n.ts | 18 +++++++++ frontend/src/markdown.css | 3 ++ frontend/src/network/models.ts | 9 +++++ frontend/src/network/network.ts | 7 ++-- frontend/src/pages/about_page.tsx | 10 +++++ frontend/src/pages/home_page.tsx | 65 ++++++++++++++++++++++--------- server/api/resource.go | 14 ++++++- server/dao/resource.go | 22 ++++++++++- server/model/sort.go | 12 ++++++ server/service/resource.go | 4 +- 11 files changed, 139 insertions(+), 27 deletions(-) create mode 100644 frontend/src/pages/about_page.tsx create mode 100644 server/model/sort.go diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx index 24e8bc0..24d5b8f 100644 --- a/frontend/src/app.tsx +++ b/frontend/src/app.tsx @@ -10,6 +10,7 @@ import ManagePage from "./pages/manage_page.tsx"; import TaggedResourcesPage from "./pages/tagged_resources_page.tsx"; import UserPage from "./pages/user_page.tsx"; import EditResourcePage from "./pages/edit_resource_page.tsx"; +import AboutPage from "./pages/about_page.tsx"; export default function App() { return ( @@ -26,6 +27,7 @@ export default function App() { }/> }/> }/> + }/> diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index 344f945..e98fed5 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -319,6 +319,15 @@ export const i18nData = { "Set the description of the tag.": "设置标签的描述。", "Use markdown format.": "使用Markdown格式。", "Tag: ": "标签: ", + + // 添加排序选项翻译 + "Select a Order": "选择排序方式", + "Latest": "最新", + "Oldest": "最早", + "Most Viewed": "浏览最多", + "Least Viewed": "浏览最少", + "Most Downloaded": "下载最多", + "Least Downloaded": "下载最少", } }, "zh-TW": { @@ -480,6 +489,15 @@ export const i18nData = { "Set the description of the tag.": "設置標籤的描述。", "Use markdown format.": "使用Markdown格式。", "Tag: ": "標籤: ", + + // 添加排序选项翻译 + "Select a Order": "選擇排序方式", + "Latest": "最新", + "Oldest": "最早", + "Most Viewed": "瀏覽最多", + "Least Viewed": "瀏覽最少", + "Most Downloaded": "下載最多", + "Least Downloaded": "下載最少", } } } diff --git a/frontend/src/markdown.css b/frontend/src/markdown.css index 20e0513..7ab41a6 100644 --- a/frontend/src/markdown.css +++ b/frontend/src/markdown.css @@ -84,6 +84,9 @@ article { border-radius: 4px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, system-ui; } + .line-break { + white-space: pre-wrap; + } } a.no-underline { diff --git a/frontend/src/network/models.ts b/frontend/src/network/models.ts index 28150d0..4d03107 100644 --- a/frontend/src/network/models.ts +++ b/frontend/src/network/models.ts @@ -126,3 +126,12 @@ export interface ServerConfig { server_description: string; site_info: string; } + +export enum RSort { + TimeAsc = 0, + TimeDesc = 1, + ViewsAsc = 2, + ViewsDesc = 3, + DownloadsAsc = 4, + DownloadsDesc = 5, +} diff --git a/frontend/src/network/network.ts b/frontend/src/network/network.ts index ab18c85..587ddec 100644 --- a/frontend/src/network/network.ts +++ b/frontend/src/network/network.ts @@ -14,7 +14,7 @@ import { UserWithToken, Comment, CommentWithResource, - ServerConfig + ServerConfig, RSort } from "./models.ts"; class Network { @@ -409,11 +409,12 @@ class Network { } } - async getResources(page: number): Promise> { + async getResources(page: number, sort: RSort): Promise> { try { const response = await axios.get(`${this.apiBaseUrl}/resource`, { params: { - page + page, + sort, } }) return response.data diff --git a/frontend/src/pages/about_page.tsx b/frontend/src/pages/about_page.tsx new file mode 100644 index 0000000..85a23b1 --- /dev/null +++ b/frontend/src/pages/about_page.tsx @@ -0,0 +1,10 @@ +import Markdown from "react-markdown"; +import {app} from "../app.ts"; + +export default function AboutPage() { + return
+ + {app.siteInfo} + +
+} \ No newline at end of file diff --git a/frontend/src/pages/home_page.tsx b/frontend/src/pages/home_page.tsx index 373f7de..3185290 100644 --- a/frontend/src/pages/home_page.tsx +++ b/frontend/src/pages/home_page.tsx @@ -2,36 +2,63 @@ import {useEffect, useState} from "react"; import ResourcesView from "../components/resources_view.tsx"; import {network} from "../network/network.ts"; import { app } from "../app.ts"; -import Markdown from "react-markdown"; +import {RSort} from "../network/models.ts"; +import Button from "../components/button.tsx"; +import {MdInfoOutline} from "react-icons/md"; import {useTranslation} from "react-i18next"; +import {useNavigate} from "react-router"; export default function HomePage() { useEffect(() => { document.title = app.appName; }, []) - const [isCollapsed, setIsCollapsed] = useState(false); + const [order, setOrder] = useState(RSort.TimeAsc) const {t} = useTranslation() + const navigate = useNavigate() + return <> - { - app.siteInfo &&
-
setIsCollapsed(!isCollapsed)}> - -
{t("About this site")}
-
{ - e.stopPropagation(); - }}> - - {app.siteInfo} - -
+
+ + +
- } - network.getResources(page)}> + +
+ network.getResources(page, order)} + /> } \ No newline at end of file diff --git a/server/api/resource.go b/server/api/resource.go index 4d384fb..0c197b1 100644 --- a/server/api/resource.go +++ b/server/api/resource.go @@ -101,7 +101,19 @@ func handleListResources(c fiber.Ctx) error { if err != nil { return model.NewRequestError("Invalid page number") } - resources, maxPage, err := service.GetResourceList(page) + sortStr := c.Query("sort") + if sortStr == "" { + sortStr = "0" + } + sortInt, err := strconv.Atoi(sortStr) + if err != nil { + return model.NewRequestError("Invalid sort parameter") + } + if sortInt < 0 || sortInt > 5 { + return model.NewRequestError("Sort parameter out of range") + } + sort := model.RSort(sortInt) + resources, maxPage, err := service.GetResourceList(page, sort) if err != nil { return err } diff --git a/server/dao/resource.go b/server/dao/resource.go index 9df0c92..59be18b 100644 --- a/server/dao/resource.go +++ b/server/dao/resource.go @@ -37,7 +37,7 @@ func GetResourceByID(id uint) (model.Resource, error) { return r, nil } -func GetResourceList(page, pageSize int) ([]model.Resource, int, error) { +func GetResourceList(page, pageSize int, sort model.RSort) ([]model.Resource, int, error) { // Retrieve a list of resources with pagination var resources []model.Resource var total int64 @@ -46,7 +46,25 @@ func GetResourceList(page, pageSize int) ([]model.Resource, int, error) { return nil, 0, err } - if err := db.Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Images").Preload("Tags").Order("created_at DESC").Find(&resources).Error; err != nil { + order := "" + switch sort { + case model.RSortTimeAsc: + order = "created_at ASC" + case model.RSortTimeDesc: + order = "created_at DESC" + case model.RSortViewsAsc: + order = "views ASC" + case model.RSortViewsDesc: + order = "views DESC" + case model.RSortDownloadsAsc: + order = "downloads ASC" + case model.RSortDownloadsDesc: + order = "downloads DESC" + default: + order = "created_at DESC" // Default sort order + } + + if err := db.Offset((page - 1) * pageSize).Limit(pageSize).Preload("User").Preload("Images").Preload("Tags").Order(order).Find(&resources).Error; err != nil { return nil, 0, err } diff --git a/server/model/sort.go b/server/model/sort.go new file mode 100644 index 0000000..9d58742 --- /dev/null +++ b/server/model/sort.go @@ -0,0 +1,12 @@ +package model + +type RSort uint8 + +const ( + RSortTimeAsc RSort = iota + RSortTimeDesc + RSortViewsAsc + RSortViewsDesc + RSortDownloadsAsc + RSortDownloadsDesc +) diff --git a/server/service/resource.go b/server/service/resource.go index a13fc49..20a6e64 100644 --- a/server/service/resource.go +++ b/server/service/resource.go @@ -125,8 +125,8 @@ func GetResource(id uint, host string) (*model.ResourceDetailView, error) { return &v, nil } -func GetResourceList(page int) ([]model.ResourceView, int, error) { - resources, totalPages, err := dao.GetResourceList(page, pageSize) +func GetResourceList(page int, sort model.RSort) ([]model.ResourceView, int, error) { + resources, totalPages, err := dao.GetResourceList(page, pageSize, sort) if err != nil { return nil, 0, err }