Skip to content

Commit c08594e

Browse files
committed
Merge branch 'main' into feature-department
# Conflicts: # bootstrap/admin_init.go
2 parents 80b9f54 + 4374429 commit c08594e

11 files changed

Lines changed: 59 additions & 28 deletions

File tree

bootstrap/admin_init.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,13 @@ func initMenu(app *Application, roleID string) {
163163
menuMgmt, _ := menu.Create().SetParentID(system.ID).SetName("菜单管理").SetSequence(1).SetType("menu").SetPath("/system/menu").SetIcon("Menu").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/menu", "GET:/api/v1/system/menu/tree").SetStatus("active").Save(ctx)
164164
roleMgmt, _ := menu.Create().SetParentID(system.ID).SetName("角色管理").SetSequence(2).SetType("menu").SetPath("/system/role").SetIcon("UserCheck").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/role").SetStatus("active").Save(ctx)
165165
userMgmt, _ := menu.Create().SetParentID(system.ID).SetName("用户管理").SetSequence(3).SetType("menu").SetPath("/system/user").SetIcon("Users").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/user/").SetStatus("active").Save(ctx)
166-
// Department management
167-
deptMgmt, _ := menu.Create().SetParentID(system.ID).SetName("部门管理").SetSequence(4).SetType("menu").SetPath("/system/departments").SetIcon("Building2").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/department/tree").SetStatus("active").Save(ctx)
168-
_, _ = menu.Create().SetParentID(system.ID).SetName("API资源").SetSequence(5).SetType("menu").SetPath("/system/api-resources").SetIcon("Code2").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
169-
loginLogs, _ := menu.Create().SetParentID(system.ID).SetName("登录日志").SetSequence(6).SetType("menu").SetPath("/system/login-logs").SetIcon("Layers3").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/login-logs").SetStatus("active").Save(ctx)
170-
dictMgmt, _ := menu.Create().SetParentID(system.ID).SetName("字典管理").SetSequence(7).SetType("menu").SetPath("/system/dict").SetIcon("BookMarked").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/dict/types", "GET:/api/v1/system/dict/items", "GET:/api/v1/system/dict/types/code/:code/items").SetStatus("active").Save(ctx)
166+
_, _ = menu.Create().SetParentID(system.ID).SetName("API资源").SetSequence(4).SetType("menu").SetPath("/system/api-resources").SetIcon("Code2").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
167+
loginLogs, _ := menu.Create().SetParentID(system.ID).SetName("登录日志").SetSequence(5).SetType("menu").SetPath("/system/login-logs").SetIcon("Layers3").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/login-logs").SetStatus("active").Save(ctx)
168+
dictMgmt, _ := menu.Create().SetParentID(system.ID).SetName("字典管理").SetSequence(6).SetType("menu").SetPath("/system/dict").SetIcon("BookMarked").SetIsFrame(false).SetVisible("show").AddAPIResourceIDs("GET:/api/v1/system/dict/types", "GET:/api/v1/system/dict/items", "GET:/api/v1/system/dict/types/code/:code/items").SetStatus("active").Save(ctx)
171169
// Menu management buttons
172-
_, _ = menu.Create().SetParentID(menuMgmt.ID).SetName("创建菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("PlusCircle").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:add").AddAPIResourceIDs("POST:/api/v1/system/menu", "GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
173-
_, _ = menu.Create().SetParentID(menuMgmt.ID).SetName("编辑菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("Edit").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:edit").AddAPIResourceIDs("PUT:/api/v1/system/menu/:id", "GET:/api/v1/system/menu/:id", "GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
174-
_, _ = menu.Create().SetParentID(menuMgmt.ID).SetName("删除菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash2").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:delete").AddAPIResourceIDs("DELETE:/api/v1/system/menu/:id").SetStatus("active").Save(ctx)
170+
menu.Create().SetParentID(menuMgmt.ID).SetName("创建菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("PlusCircle").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:add").AddAPIResourceIDs("POST:/api/v1/system/menu", "GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
171+
menu.Create().SetParentID(menuMgmt.ID).SetName("编辑菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("Edit").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:edit").AddAPIResourceIDs("PUT:/api/v1/system/menu/:id", "GET:/api/v1/system/menu/:id", "GET:/api/v1/system/api-resources").SetStatus("active").Save(ctx)
172+
menu.Create().SetParentID(menuMgmt.ID).SetName("删除菜单").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash2").SetIsFrame(false).SetVisible("show").SetPermissions("system:menu:delete").AddAPIResourceIDs("DELETE:/api/v1/system/menu/:id").SetStatus("active").Save(ctx)
175173
// Role management buttons
176174
menu.Create().SetParentID(roleMgmt.ID).SetName("创建角色").SetSequence(0).SetType("button").SetPath("").SetIcon("Plus").SetIsFrame(false).SetVisible("show").SetPermissions("system:role:add").AddAPIResourceIDs("POST:/api/v1/system/role", "GET:/api/v1/system/menu/tree").SetStatus("active").Save(ctx)
177175
menu.Create().SetParentID(roleMgmt.ID).SetName("删除角色").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash2").SetIsFrame(false).SetVisible("show").SetPermissions("system:role:delete").AddAPIResourceIDs("DELETE:/api/v1/system/role/:id").SetStatus("active").Save(ctx)
@@ -181,11 +179,7 @@ func initMenu(app *Application, roleID string) {
181179
menu.Create().SetParentID(userMgmt.ID).SetName("邀请用户").SetSequence(0).SetType("button").SetPath("").SetIcon("Phone").SetIsFrame(false).SetVisible("show").SetPermissions("system:user:invite").AddAPIResourceIDs("POST:/api/v1/system/user/invite").SetStatus("active").Save(ctx)
182180
menu.Create().SetParentID(userMgmt.ID).SetName("删除用户").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash").SetIsFrame(false).SetVisible("show").SetPermissions("system:user:delete").AddAPIResourceIDs("DELETE:/api/v1/system/user/:id").SetStatus("active").Save(ctx)
183181
menu.Create().SetParentID(userMgmt.ID).SetName("编辑用户").SetSequence(0).SetType("button").SetPath("").SetIcon("Edit").SetIsFrame(false).SetVisible("show").SetPermissions("system:user:edit").AddAPIResourceIDs("PUT:/api/v1/system/user/:id", "GET:/api/v1/system/user/:id", "GET:/api/v1/system/user/:id/roles").SetStatus("active").Save(ctx)
184-
// Department management buttons
185-
menu.Create().SetParentID(deptMgmt.ID).SetName("创建部门").SetSequence(0).SetType("button").SetPath("").SetIcon("PlusCircle").SetIsFrame(false).SetVisible("show").SetPermissions("system:dept:add").AddAPIResourceIDs("POST:/api/v1/system/department").SetStatus("active").Save(ctx)
186-
menu.Create().SetParentID(deptMgmt.ID).SetName("编辑部门").SetSequence(0).SetType("button").SetPath("").SetIcon("Edit").SetIsFrame(false).SetVisible("show").SetPermissions("system:dept:edit").AddAPIResourceIDs("PUT:/api/v1/system/department/:id", "GET:/api/v1/system/department/:id").SetStatus("active").Save(ctx)
187-
menu.Create().SetParentID(deptMgmt.ID).SetName("删除部门").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash2").SetIsFrame(false).SetVisible("show").SetPermissions("system:dept:delete").AddAPIResourceIDs("DELETE:/api/v1/system/department/:id").SetStatus("active").Save(ctx)
188-
// API log button
182+
// Log button
189183
menu.Create().SetParentID(loginLogs.ID).SetName("清空日志").SetSequence(0).SetType("button").SetPath("").SetIcon("Trash2").SetIsFrame(false).SetVisible("show").SetPermissions("system:login_logs:clean").AddAPIResourceIDs("DELETE:/api/v1/system/login-logs").SetStatus("active").Save(ctx)
190184
// Dictionary buttons (types & items)
191185
menu.Create().SetParentID(dictMgmt.ID).SetName("创建字典类型").SetSequence(0).SetType("button").SetPath("").SetIcon("PlusCircle").SetIsFrame(false).SetVisible("show").SetPermissions("system:dict:add_type").AddAPIResourceIDs("POST:/api/v1/system/dict/types").SetStatus("active").Save(ctx)

docs/docs.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3306,6 +3306,9 @@ const docTemplate = `{
33063306
"domain.Profile": {
33073307
"type": "object",
33083308
"properties": {
3309+
"bio": {
3310+
"type": "string"
3311+
},
33093312
"created_at": {
33103313
"type": "string"
33113314
},
@@ -3315,9 +3318,6 @@ const docTemplate = `{
33153318
"id": {
33163319
"type": "string"
33173320
},
3318-
"is_admin": {
3319-
"type": "boolean"
3320-
},
33213321
"phone": {
33223322
"type": "string"
33233323
},
@@ -3338,6 +3338,9 @@ const docTemplate = `{
33383338
"avatar": {
33393339
"type": "string"
33403340
},
3341+
"bio": {
3342+
"type": "string"
3343+
},
33413344
"name": {
33423345
"type": "string"
33433346
}

docs/swagger.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3300,6 +3300,9 @@
33003300
"domain.Profile": {
33013301
"type": "object",
33023302
"properties": {
3303+
"bio": {
3304+
"type": "string"
3305+
},
33033306
"created_at": {
33043307
"type": "string"
33053308
},
@@ -3309,9 +3312,6 @@
33093312
"id": {
33103313
"type": "string"
33113314
},
3312-
"is_admin": {
3313-
"type": "boolean"
3314-
},
33153315
"phone": {
33163316
"type": "string"
33173317
},
@@ -3332,6 +3332,9 @@
33323332
"avatar": {
33333333
"type": "string"
33343334
},
3335+
"bio": {
3336+
"type": "string"
3337+
},
33353338
"name": {
33363339
"type": "string"
33373340
}

docs/swagger.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,14 +454,14 @@ definitions:
454454
type: object
455455
domain.Profile:
456456
properties:
457+
bio:
458+
type: string
457459
created_at:
458460
type: string
459461
email:
460462
type: string
461463
id:
462464
type: string
463-
is_admin:
464-
type: boolean
465465
phone:
466466
type: string
467467
status:
@@ -475,6 +475,8 @@ definitions:
475475
properties:
476476
avatar:
477477
type: string
478+
bio:
479+
type: string
478480
name:
479481
type: string
480482
type: object

domain/auth.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type RefreshTokenResponse struct {
3131
type ProfileUpdate struct {
3232
Name string `json:"name"`
3333
Avatar string `json:"avatar"`
34+
Bio string `json:"bio"`
3435
}
3536

3637
// PasswordUpdate 密码更新请求

domain/profile.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ type Profile struct {
1010
Username string `json:"username"`
1111
Email string `json:"email"`
1212
Phone string `json:"phone"`
13+
Bio string `json:"bio"`
1314
Status string `json:"status"`
1415
CreatedAt time.Time `json:"created_at"`
1516
UpdatedAt time.Time `json:"updated_at"`

ent/schema/user.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ func (User) Fields() []ent.Field {
5656
field.String("password").
5757
Sensitive().
5858
MaxLen(128),
59+
field.String("bio").
60+
Optional().
61+
MaxLen(160),
5962
field.Time("created_at").
6063
Default(time.Now),
6164
field.Time("updated_at").

repository/profile_repository.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ func (pr *entProfileRepository) GetByID(c context.Context, id string) (*domain.P
3333
Username: u.Username,
3434
Email: u.Email,
3535
Phone: u.Phone,
36+
Bio: u.Bio,
3637
Status: string(u.Status),
3738
CreatedAt: u.CreatedAt,
3839
UpdatedAt: u.UpdatedAt,
@@ -51,6 +52,9 @@ func (pr *entProfileRepository) UpdateProfile(c context.Context, userID string,
5152
if updateData.Avatar != "" {
5253
updateQuery = updateQuery.SetAvatar(updateData.Avatar)
5354
}
55+
if updateData.Avatar != "" {
56+
updateQuery = updateQuery.SetBio(updateData.Bio)
57+
}
5458

5559
_, err := updateQuery.Save(c)
5660
return err

web/src/features/settings/profile/profile-form.tsx

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { useEffect } from 'react'
1+
import { useEffect, useState } from 'react'
22
import { z } from 'zod'
33
import { useForm } from 'react-hook-form'
44
import { zodResolver } from '@hookform/resolvers/zod'
5+
import { toast } from 'sonner'
56
import { useAuthStore } from '@/stores/auth-store'
6-
import { showSubmittedData } from '@/lib/show-submitted-data'
7+
import { updateProfile } from '@/services'
78
import { Button } from '@/components/ui/button'
89
import {
910
Form,
@@ -35,9 +36,10 @@ const defaultValues: Partial<ProfileFormValues> = {
3536
}
3637

3738
export function ProfileForm() {
38-
const { profile, fetchProfile, isLoadingProfile } = useAuthStore(
39+
const { profile, fetchProfile, isLoadingProfile, setProfile } = useAuthStore(
3940
(state) => state.auth
4041
)
42+
const [isPending, setIsPending] = useState(false)
4143

4244
const form = useForm<ProfileFormValues>({
4345
resolver: zodResolver(profileFormSchema),
@@ -56,15 +58,30 @@ export function ProfileForm() {
5658
form.reset({
5759
username: profile.username || '',
5860
email: profile.email || '',
59-
bio: '', // Keep bio empty as it's not part of the Profile type
61+
bio: profile.bio || '',
6062
})
6163
}
6264
}, [profile, form])
6365

66+
async function onSubmit(data: ProfileFormValues) {
67+
try {
68+
setIsPending(true)
69+
await updateProfile({ bio: data.bio })
70+
// Refresh profile in store to reflect changes
71+
const updatedProfile = profile ? { ...profile, bio: data.bio } : profile
72+
setProfile(updatedProfile)
73+
toast.success('个人资料更新成功!')
74+
} catch {
75+
toast.error('更新失败,请重试。')
76+
} finally {
77+
setIsPending(false)
78+
}
79+
}
80+
6481
return (
6582
<Form {...form}>
6683
<form
67-
onSubmit={form.handleSubmit((data) => showSubmittedData(data))}
84+
onSubmit={form.handleSubmit(onSubmit)}
6885
className='space-y-8'
6986
>
7087
<FormField
@@ -118,8 +135,8 @@ export function ProfileForm() {
118135
</FormItem>
119136
)}
120137
/>
121-
<Button type='submit' disabled={isLoadingProfile}>
122-
{isLoadingProfile ? '加载中...' : '更新个人资料'}
138+
<Button type='submit' disabled={isLoadingProfile || isPending}>
139+
{isPending ? '保存中...' : isLoadingProfile ? '加载中...' : '更新个人资料'}
123140
</Button>
124141
</form>
125142
</Form>

web/src/types/profile.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export interface Profile {
55
username: string
66
email: string
77
phone?: string
8+
bio?: string
89
avatar?: string
910
status: UserStatus
1011
created_at: Date
@@ -16,6 +17,7 @@ export interface ProfileUpdateRequest {
1617
username?: string
1718
email?: string
1819
phone?: string
20+
bio?: string
1921
avatar?: string
2022
}
2123

0 commit comments

Comments
 (0)