Skip to content

Commit ee5e80d

Browse files
feat: Improve user list sorting
1 parent 767d665 commit ee5e80d

2 files changed

Lines changed: 37 additions & 7 deletions

File tree

backend/apps/system/api/user.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,34 @@ async def pager(
5858
status: Optional[int] = Query(None, description=f"{PLACEHOLDER_PREFIX}status"),
5959
origins: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}origin"),
6060
oidlist: Optional[list[int]] = Query(None, description=f"{PLACEHOLDER_PREFIX}oid"),
61+
order_by: Optional[str] = Query(None, description="排序字段"),
62+
desc: Optional[bool] = Query(False, description="是否降序"),
6163
):
6264
pagination = PaginationParams(page=pageNum, size=pageSize)
6365
paginator = Paginator(session)
64-
filters = {}
65-
66+
67+
# 允许排序的字段白名单(防止 SQL 注入)
68+
SORT_COLUMNS = {
69+
'account': UserModel.account,
70+
'create_time': UserModel.create_time,
71+
'name': UserModel.name,
72+
'email': UserModel.email,
73+
'status': UserModel.status,
74+
}
75+
sort_field = SORT_COLUMNS.get(order_by, UserModel.account)
76+
sort_clause = sort_field.desc() if desc else sort_field.asc()
77+
78+
# SELECT 列必须包含 ORDER BY 列(PostgreSQL DISTINCT 约束)
79+
select_columns = [UserModel.id, UserModel.account]
80+
if order_by and order_by != 'account':
81+
select_columns.append(sort_field)
82+
6683
origin_stmt = (
67-
select(UserModel.id, UserModel.account)
84+
select(*select_columns)
6885
.join(UserWsModel, UserModel.id == UserWsModel.uid, isouter=True)
6986
.where(UserModel.id != 1)
7087
.distinct()
71-
.order_by(UserModel.account)
88+
.order_by(sort_clause)
7289
)
7390

7491
if oidlist:
@@ -89,16 +106,15 @@ async def pager(
89106

90107
user_page = await paginator.get_paginated_response(
91108
stmt=origin_stmt,
92-
pagination=pagination,
93-
**filters)
109+
pagination=pagination)
94110
uid_list = [item.get('id') for item in user_page.items]
95111
if not uid_list:
96112
return user_page
97113
stmt = (
98114
select(UserModel, UserWsModel.oid.label('ws_oid'))
99115
.join(UserWsModel, UserModel.id == UserWsModel.uid, isouter=True)
100116
.where(UserModel.id.in_(uid_list))
101-
.order_by(UserModel.account, UserModel.create_time)
117+
.order_by(sort_clause)
102118
)
103119
user_workspaces = session.exec(stmt).all()
104120
merged = defaultdict(list)

frontend/src/views/system/user/User.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
:data="state.tableData"
9797
style="width: 100%"
9898
@selection-change="handleSelectionChange"
99+
@sort-change="handleSortChange"
99100
>
100101
<el-table-column type="selection" width="55" />
101102
<el-table-column prop="name" show-overflow-tooltip :label="$t('user.name')" width="280" />
@@ -651,6 +652,8 @@ const state = reactive<any>({
651652
currentPage: 1,
652653
pageSize: 20,
653654
total: 0,
655+
sortColumn: '',
656+
sortOrder: '', // 'ascending' | 'descending' | ''
654657
},
655658
})
656659
@@ -1004,6 +1007,11 @@ const configParams = () => {
10041007
})
10051008
})
10061009
1010+
if (state.pageInfo.sortColumn) {
1011+
str += str ? `&order_by=${state.pageInfo.sortColumn}` : `order_by=${state.pageInfo.sortColumn}`
1012+
str += `&desc=${state.pageInfo.sortOrder === 'descending'}`
1013+
}
1014+
10071015
if (str.length) {
10081016
str = `?${str}`
10091017
}
@@ -1146,6 +1154,12 @@ const handleCurrentChange = (val: number) => {
11461154
state.pageInfo.currentPage = val
11471155
search()
11481156
}
1157+
const handleSortChange = ({ prop, order }: any) => {
1158+
state.pageInfo.sortColumn = order ? prop : ''
1159+
state.pageInfo.sortOrder = order || ''
1160+
state.pageInfo.currentPage = 1
1161+
search()
1162+
}
11491163
const formatSpaceName = (row_oid_list: Array<any>) => {
11501164
if (!row_oid_list?.length) {
11511165
return '-'

0 commit comments

Comments
 (0)