From 8afed631427fa986ee16ec44686c88703829cbdb Mon Sep 17 00:00:00 2001 From: yanghao05 Date: Fri, 18 Apr 2025 22:38:57 +0800 Subject: [PATCH] feat: update user detail --- backend/app/http/admin/routes.gen.go | 11 ++ backend/app/http/admin/users.go | 16 +++ backend/app/models/posts.go | 57 ++++++++++ frontend/admin/src/api/userService.js | 6 + frontend/admin/src/api/user_articles.json | 57 ++++++++++ frontend/admin/src/pages/UserDetail.vue | 127 ++++++++++++++++++++++ frontend/admin/src/pages/UserPage.vue | 5 +- frontend/admin/src/router.js | 6 + 8 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 frontend/admin/src/api/user_articles.json create mode 100644 frontend/admin/src/pages/UserDetail.vue diff --git a/backend/app/http/admin/routes.gen.go b/backend/app/http/admin/routes.gen.go index d9fa8c8..560c066 100644 --- a/backend/app/http/admin/routes.gen.go +++ b/backend/app/http/admin/routes.gen.go @@ -116,4 +116,15 @@ func (r *Routes) Register(router fiber.Router) { Query[UserListQuery]("query"), )) + router.Get("/v1/admin/users/:id", DataFunc1( + r.users.Show, + PathParam[int64]("id"), + )) + + router.Get("/v1/admin/users/:id/articles", DataFunc2( + r.users.Articles, + PathParam[int64]("id"), + Query[requests.Pagination]("pagination"), + )) + } diff --git a/backend/app/http/admin/users.go b/backend/app/http/admin/users.go index c6469b8..2d0c845 100644 --- a/backend/app/http/admin/users.go +++ b/backend/app/http/admin/users.go @@ -3,6 +3,7 @@ package admin import ( "quyun/app/models" "quyun/app/requests" + "quyun/database/schemas/public/model" "github.com/gofiber/fiber/v3" ) @@ -22,3 +23,18 @@ func (ctl *users) List(ctx fiber.Ctx, pagination *requests.Pagination, query *Us cond := models.Users.BuildConditionWithKey(query.Keyword) return models.Users.List(ctx.Context(), pagination, cond) } + +// Show user +// @Router /v1/admin/users/:id [get] +// @Bind id path +func (ctl *users) Show(ctx fiber.Ctx, id int64) (*model.Users, error) { + return models.Users.GetByID(ctx.Context(), id) +} + +// Articles show user bought articles +// @Router /v1/admin/users/:id/articles [get] +// @Bind id path +// @Bind pagination query +func (ctl *users) Articles(ctx fiber.Ctx, id int64, pagination *requests.Pagination) (*requests.Pager, error) { + return models.Posts.Bought(ctx.Context(), id, pagination) +} diff --git a/backend/app/models/posts.go b/backend/app/models/posts.go index b0344e7..3888954 100644 --- a/backend/app/models/posts.go +++ b/backend/app/models/posts.go @@ -286,3 +286,60 @@ func (m *postsModel) BoughtStatistics(ctx context.Context, postIds []int64) (map return resultMap, nil } + +// Bought +func (m *postsModel) Bought(ctx context.Context, userId int64, pagination *requests.Pagination) (*requests.Pager, error) { + pagination.Format() + + // select up.price,up.created_at,p.* from user_posts up left join posts p on up.post_id = p.id where up.user_id =1 + tbl := table.UserPosts + stmt := tbl. + SELECT( + tbl.Price.AS("price"), + tbl.CreatedAt.AS("bought_at"), + table.Posts.Title.AS("title"), + ). + FROM( + tbl.INNER_JOIN(table.Posts, table.Posts.ID.EQ(tbl.PostID)), + ). + WHERE( + tbl.UserID.EQ(Int64(1)), + ). + ORDER_BY(tbl.ID.DESC()). + LIMIT(pagination.Limit). + OFFSET(pagination.Offset) + + m.log.Infof("sql: %s", stmt.DebugSql()) + + var items []struct { + Title string `json:"title"` + Price int64 `json:"price"` + BoughtAt time.Time `json:"bought_at"` + } + + if err := stmt.QueryContext(ctx, db, &items); err != nil { + m.log.Errorf("error getting bought posts: %v", err) + return nil, err + } + + // convert to model.Posts + var cnt struct { + Cnt int64 + } + stmtCnt := tbl. + SELECT(COUNT(tbl.ID).AS("cnt")). + WHERE( + tbl.UserID.EQ(Int64(userId)), + ) + + if err := stmtCnt.QueryContext(ctx, db, &cnt); err != nil { + m.log.Errorf("error getting bought posts count: %v", err) + return nil, err + } + + return &requests.Pager{ + Items: items, + Total: cnt.Cnt, + Pagination: *pagination, + }, nil +} diff --git a/frontend/admin/src/api/userService.js b/frontend/admin/src/api/userService.js index 10bb024..84fa150 100644 --- a/frontend/admin/src/api/userService.js +++ b/frontend/admin/src/api/userService.js @@ -19,4 +19,10 @@ export const userService = { deleteUser(id) { return httpClient.delete(`/admin/users/${id}`); }, + getUserById(id) { + return httpClient.get(`/admin/users/${id}`); + }, + getUserArticles(userId) { + return httpClient.get(`/admin/users/${userId}/articles`); + } } \ No newline at end of file diff --git a/frontend/admin/src/api/user_articles.json b/frontend/admin/src/api/user_articles.json new file mode 100644 index 0000000..6061ccb --- /dev/null +++ b/frontend/admin/src/api/user_articles.json @@ -0,0 +1,57 @@ +{ + "page": 1, + "limit": 10, + "total": 10, + "items": [ + { + "title": "test-title-9", + "price": 0, + "bought_at": "2025-04-11T15:08:06.629569Z" + }, + { + "title": "test-title-8", + "price": 0, + "bought_at": "2025-04-11T15:08:06.625099Z" + }, + { + "title": "test-title-7", + "price": 0, + "bought_at": "2025-04-11T15:08:06.62019Z" + }, + { + "title": "test-title-6", + "price": 0, + "bought_at": "2025-04-11T15:08:06.614768Z" + }, + { + "title": "test-title-5", + "price": 0, + "bought_at": "2025-04-11T15:08:06.610985Z" + }, + { + "title": "test-title-4", + "price": 0, + "bought_at": "2025-04-11T15:08:06.605659Z" + }, + { + "title": "test-title-3", + "price": 0, + "bought_at": "2025-04-11T15:08:06.602181Z" + }, + { + "title": "test-title-2", + "price": 0, + "bought_at": "2025-04-11T15:08:06.599001Z" + }, + { + "title": "test-title-1", + "price": 0, + "bought_at": "2025-04-11T15:08:06.594752Z" + }, + { + "title": "test-title-0", + "price": 0, + "bought_at": "2025-04-11T15:08:06.585365Z" + } + ] +} \ No newline at end of file diff --git a/frontend/admin/src/pages/UserDetail.vue b/frontend/admin/src/pages/UserDetail.vue new file mode 100644 index 0000000..e205fda --- /dev/null +++ b/frontend/admin/src/pages/UserDetail.vue @@ -0,0 +1,127 @@ + + + diff --git a/frontend/admin/src/pages/UserPage.vue b/frontend/admin/src/pages/UserPage.vue index ce79d9b..129749f 100644 --- a/frontend/admin/src/pages/UserPage.vue +++ b/frontend/admin/src/pages/UserPage.vue @@ -140,7 +140,10 @@ onMounted(() => {
-
{{ data.username }}
+ + {{ data.username }} +
diff --git a/frontend/admin/src/router.js b/frontend/admin/src/router.js index e285f5f..1e67427 100644 --- a/frontend/admin/src/router.js +++ b/frontend/admin/src/router.js @@ -41,6 +41,12 @@ const routes = [ name: 'Users', component: () => import('./pages/UserPage.vue'), }, + { + path: '/users/:id', + name: 'UserDetail', + component: () => import('./pages/UserDetail.vue'), + props: true + }, { path: '/orders', name: 'Orders',