Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
7a0de176
Commit
7a0de176
authored
Dec 27, 2025
by
IanShaw027
Browse files
refactor(frontend): 优化管理后台视图
- 改进账户管理视图 - 优化分组管理界面 - 完善代理管理功能 - 增强兑换码管理 - 改进订阅管理视图 - 优化使用统计展示 - 完善用户管理界面
parent
35b1bc37
Changes
7
Hide whitespace changes
Inline
Side-by-side
frontend/src/views/admin/AccountsView.vue
View file @
7a0de176
...
@@ -280,8 +280,7 @@
...
@@ -280,8 +280,7 @@
<!--
主要操作
:
编辑和删除
(
始终显示
)
-->
<!--
主要操作
:
编辑和删除
(
始终显示
)
-->
<
button
<
button
@
click
=
"
handleEdit(row)
"
@
click
=
"
handleEdit(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400
"
:
title
=
"
t('common.edit')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -296,11 +295,11 @@
...
@@ -296,11 +295,11 @@
d
=
"
M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10
"
d
=
"
M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
common.edit
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
button
<
button
@
click
=
"
handleDelete(row)
"
@
click
=
"
handleDelete(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
:
title
=
"
t('common.delete')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -315,6 +314,7 @@
...
@@ -315,6 +314,7 @@
d
=
"
M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0
"
d
=
"
M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
common.delete
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<!--
次要操作
:
展开时显示
-->
<!--
次要操作
:
展开时显示
-->
...
@@ -323,8 +323,7 @@
...
@@ -323,8 +323,7 @@
<
button
<
button
v
-
if
=
"
row.status === 'error'
"
v
-
if
=
"
row.status === 'error'
"
@
click
=
"
handleResetStatus(row)
"
@
click
=
"
handleResetStatus(row)
"
class
=
"
rounded-lg p-2 text-red-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-red-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
:
title
=
"
t('admin.accounts.resetStatus')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -339,13 +338,13 @@
...
@@ -339,13 +338,13 @@
d
=
"
M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3
"
d
=
"
M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.resetStatus
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<!--
Clear
Rate
Limit
button
-->
<!--
Clear
Rate
Limit
button
-->
<
button
<
button
v
-
if
=
"
isRateLimited(row) || isOverloaded(row)
"
v
-
if
=
"
isRateLimited(row) || isOverloaded(row)
"
@
click
=
"
handleClearRateLimit(row)
"
@
click
=
"
handleClearRateLimit(row)
"
class
=
"
rounded-lg p-2 text-amber-500 transition-colors hover:bg-amber-50 hover:text-amber-600 dark:hover:bg-amber-900/20 dark:hover:text-amber-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-amber-500 transition-colors hover:bg-amber-50 hover:text-amber-600 dark:hover:bg-amber-900/20 dark:hover:text-amber-400
"
:
title
=
"
t('admin.accounts.clearRateLimit')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -360,12 +359,12 @@
...
@@ -360,12 +359,12 @@
d
=
"
M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z
"
d
=
"
M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.clearRateLimit
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<!--
Test
Connection
button
-->
<!--
Test
Connection
button
-->
<
button
<
button
@
click
=
"
handleTest(row)
"
@
click
=
"
handleTest(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400
"
:
title
=
"
t('admin.accounts.testConnection')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -380,12 +379,12 @@
...
@@ -380,12 +379,12 @@
d
=
"
M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 010 1.972l-11.54 6.347a1.125 1.125 0 01-1.667-.986V5.653z
"
d
=
"
M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 010 1.972l-11.54 6.347a1.125 1.125 0 01-1.667-.986V5.653z
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.testConnection
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<!--
View
Stats
button
-->
<!--
View
Stats
button
-->
<
button
<
button
@
click
=
"
handleViewStats(row)
"
@
click
=
"
handleViewStats(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-indigo-50 hover:text-indigo-600 dark:hover:bg-indigo-900/20 dark:hover:text-indigo-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-indigo-50 hover:text-indigo-600 dark:hover:bg-indigo-900/20 dark:hover:text-indigo-400
"
:
title
=
"
t('admin.accounts.viewStats')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -400,12 +399,12 @@
...
@@ -400,12 +399,12 @@
d
=
"
M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z
"
d
=
"
M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.viewStats
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
button
<
button
v
-
if
=
"
row.type === 'oauth' || row.type === 'setup-token'
"
v
-
if
=
"
row.type === 'oauth' || row.type === 'setup-token'
"
@
click
=
"
handleReAuth(row)
"
@
click
=
"
handleReAuth(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-blue-50 hover:text-blue-600 dark:hover:bg-blue-900/20 dark:hover:text-blue-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-blue-50 hover:text-blue-600 dark:hover:bg-blue-900/20 dark:hover:text-blue-400
"
:
title
=
"
t('admin.accounts.reAuthorize')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -420,12 +419,12 @@
...
@@ -420,12 +419,12 @@
d
=
"
M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244
"
d
=
"
M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.reAuthorize
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
button
<
button
v
-
if
=
"
row.type === 'oauth' || row.type === 'setup-token'
"
v
-
if
=
"
row.type === 'oauth' || row.type === 'setup-token'
"
@
click
=
"
handleRefreshToken(row)
"
@
click
=
"
handleRefreshToken(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-purple-50 hover:text-purple-600 dark:hover:bg-purple-900/20 dark:hover:text-purple-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-purple-50 hover:text-purple-600 dark:hover:bg-purple-900/20 dark:hover:text-purple-400
"
:
title
=
"
t('admin.accounts.refreshToken')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -440,6 +439,7 @@
...
@@ -440,6 +439,7 @@
d
=
"
M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99
"
d
=
"
M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.accounts.refreshToken
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
/template
>
<
/template
>
<
/div
>
<
/div
>
...
...
frontend/src/views/admin/GroupsView.vue
View file @
7a0de176
...
@@ -166,8 +166,7 @@
...
@@ -166,8 +166,7 @@
<
div
class
=
"
flex items-center gap-1
"
>
<
div
class
=
"
flex items-center gap-1
"
>
<
button
<
button
@
click
=
"
handleEdit(row)
"
@
click
=
"
handleEdit(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400
"
:
title
=
"
t('common.edit')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -182,11 +181,11 @@
...
@@ -182,11 +181,11 @@
d
=
"
M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10
"
d
=
"
M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
common.edit
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
button
<
button
@
click
=
"
handleDelete(row)
"
@
click
=
"
handleDelete(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
:
title
=
"
t('common.delete')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -201,6 +200,7 @@
...
@@ -201,6 +200,7 @@
d
=
"
M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0
"
d
=
"
M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
common.delete
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
/div
>
<
/div
>
<
/template
>
<
/template
>
...
...
frontend/src/views/admin/ProxiesView.vue
View file @
7a0de176
...
@@ -112,8 +112,7 @@
...
@@ -112,8 +112,7 @@
<button
<button
@
click=
"handleTestConnection(row)"
@
click=
"handleTestConnection(row)"
:disabled=
"testingProxyIds.has(row.id)"
:disabled=
"testingProxyIds.has(row.id)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-emerald-50 hover:text-emerald-600 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-emerald-900/20 dark:hover:text-emerald-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-emerald-50 hover:text-emerald-600 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-emerald-900/20 dark:hover:text-emerald-400"
:title=
"t('admin.proxies.testConnection')"
>
>
<svg
<svg
v-if=
"testingProxyIds.has(row.id)"
v-if=
"testingProxyIds.has(row.id)"
...
@@ -149,11 +148,11 @@
...
@@ -149,11 +148,11 @@
d=
"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
d=
"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
admin.proxies.testConnection
'
)
}}
</span>
</button>
</button>
<button
<button
@
click=
"handleEdit(row)"
@
click=
"handleEdit(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400"
:title=
"t('common.edit')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -168,11 +167,11 @@
...
@@ -168,11 +167,11 @@
d=
"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
d=
"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
common.edit
'
)
}}
</span>
</button>
</button>
<button
<button
@
click=
"handleDelete(row)"
@
click=
"handleDelete(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
:title=
"t('common.delete')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -187,6 +186,7 @@
...
@@ -187,6 +186,7 @@
d=
"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
d=
"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
common.delete
'
)
}}
</span>
</button>
</button>
</div>
</div>
</
template
>
</
template
>
...
...
frontend/src/views/admin/RedeemView.vue
View file @
7a0de176
...
@@ -161,8 +161,7 @@
...
@@ -161,8 +161,7 @@
<
button
<
button
v
-
if
=
"
row.status === 'unused'
"
v
-
if
=
"
row.status === 'unused'
"
@
click
=
"
handleDelete(row)
"
@
click
=
"
handleDelete(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
:
title
=
"
t('common.delete')
"
>
>
<
svg
class
=
"
h-4 w-4
"
fill
=
"
none
"
stroke
=
"
currentColor
"
viewBox
=
"
0 0 24 24
"
>
<
svg
class
=
"
h-4 w-4
"
fill
=
"
none
"
stroke
=
"
currentColor
"
viewBox
=
"
0 0 24 24
"
>
<
path
<
path
...
@@ -172,6 +171,7 @@
...
@@ -172,6 +171,7 @@
d
=
"
M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16
"
d
=
"
M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
common.delete
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
span
v
-
else
class
=
"
text-gray-400 dark:text-dark-500
"
>-<
/span
>
<
span
v
-
else
class
=
"
text-gray-400 dark:text-dark-500
"
>-<
/span
>
<
/div
>
<
/div
>
...
...
frontend/src/views/admin/SubscriptionsView.vue
View file @
7a0de176
...
@@ -257,8 +257,7 @@
...
@@ -257,8 +257,7 @@
<
button
<
button
v
-
if
=
"
row.status === 'active'
"
v
-
if
=
"
row.status === 'active'
"
@
click
=
"
handleExtend(row)
"
@
click
=
"
handleExtend(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400
"
:
title
=
"
t('admin.subscriptions.extend')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -273,12 +272,12 @@
...
@@ -273,12 +272,12 @@
d
=
"
M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z
"
d
=
"
M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.subscriptions.extend
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
button
<
button
v
-
if
=
"
row.status === 'active'
"
v
-
if
=
"
row.status === 'active'
"
@
click
=
"
handleRevoke(row)
"
@
click
=
"
handleRevoke(row)
"
class
=
"
rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
class
=
"
flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400
"
:
title
=
"
t('admin.subscriptions.revoke')
"
>
>
<
svg
<
svg
class
=
"
h-4 w-4
"
class
=
"
h-4 w-4
"
...
@@ -293,6 +292,7 @@
...
@@ -293,6 +292,7 @@
d
=
"
M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636
"
d
=
"
M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636
"
/>
/>
<
/svg
>
<
/svg
>
<
span
class
=
"
text-xs
"
>
{{
t
(
'
admin.subscriptions.revoke
'
)
}}
<
/span
>
<
/button
>
<
/button
>
<
/div
>
<
/div
>
<
/template
>
<
/template
>
...
...
frontend/src/views/admin/UsageView.vue
View file @
7a0de176
...
@@ -455,7 +455,11 @@
...
@@ -455,7 +455,11 @@
$
{{
row
.
actual_cost
.
toFixed
(
6
)
}}
$
{{
row
.
actual_cost
.
toFixed
(
6
)
}}
</span>
</span>
<!-- Cost Detail Tooltip -->
<!-- Cost Detail Tooltip -->
<div
class=
"group relative"
>
<div
class=
"group relative"
@
mouseenter=
"showTooltip($event, row)"
@
mouseleave=
"hideTooltip"
>
<div
<div
class=
"flex h-4 w-4 cursor-help items-center justify-center rounded-full bg-gray-100 transition-colors group-hover:bg-blue-100 dark:bg-gray-700 dark:group-hover:bg-blue-900/50"
class=
"flex h-4 w-4 cursor-help items-center justify-center rounded-full bg-gray-100 transition-colors group-hover:bg-blue-100 dark:bg-gray-700 dark:group-hover:bg-blue-900/50"
>
>
...
@@ -471,60 +475,6 @@
...
@@ -471,60 +475,6 @@
/>
/>
</svg>
</svg>
</div>
</div>
<!-- Tooltip Content (right side) -->
<div
class=
"invisible absolute left-full top-1/2 z-[100] ml-2 -translate-y-1/2 opacity-0 transition-all duration-200 group-hover:visible group-hover:opacity-100"
>
<div
class=
"whitespace-nowrap rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-xs text-white shadow-xl dark:border-gray-600 dark:bg-gray-800"
>
<div
class=
"space-y-1.5"
>
<!-- Cost Breakdown -->
<div
class=
"mb-2 border-b border-gray-700 pb-1.5"
>
<div
class=
"text-xs font-semibold text-gray-300 mb-1"
>
成本明细
</div>
<div
v-if=
"row.input_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
admin.usage.inputCost
'
)
}}
</span>
<span
class=
"font-medium text-white"
>
$
{{
row
.
input_cost
.
toFixed
(
6
)
}}
</span>
</div>
<div
v-if=
"row.output_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
admin.usage.outputCost
'
)
}}
</span>
<span
class=
"font-medium text-white"
>
$
{{
row
.
output_cost
.
toFixed
(
6
)
}}
</span>
</div>
<div
v-if=
"row.cache_creation_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
admin.usage.cacheCreationCost
'
)
}}
</span>
<span
class=
"font-medium text-white"
>
$
{{
row
.
cache_creation_cost
.
toFixed
(
6
)
}}
</span>
</div>
<div
v-if=
"row.cache_read_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
admin.usage.cacheReadCost
'
)
}}
</span>
<span
class=
"font-medium text-white"
>
$
{{
row
.
cache_read_cost
.
toFixed
(
6
)
}}
</span>
</div>
</div>
<!-- Rate and Summary -->
<div
class=
"flex items-center justify-between gap-6"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
usage.rate
'
)
}}
</span>
<span
class=
"font-semibold text-blue-400"
>
{{
(
row
.
rate_multiplier
||
1
).
toFixed
(
2
)
}}
x
</span
>
</div>
<div
class=
"flex items-center justify-between gap-6"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
usage.original
'
)
}}
</span>
<span
class=
"font-medium text-white"
>
$
{{
row
.
total_cost
.
toFixed
(
6
)
}}
</span>
</div>
<div
class=
"flex items-center justify-between gap-6 border-t border-gray-700 pt-1.5"
>
<span
class=
"text-gray-400"
>
{{
t
(
'
usage.billed
'
)
}}
</span>
<span
class=
"font-semibold text-green-400"
>
$
{{
row
.
actual_cost
.
toFixed
(
6
)
}}
</span
>
</div>
</div>
<!-- Tooltip Arrow (left side) -->
<div
class=
"absolute right-full top-1/2 h-0 w-0 -translate-y-1/2 border-b-[6px] border-r-[6px] border-t-[6px] border-b-transparent border-r-gray-900 border-t-transparent dark:border-r-gray-800"
></div>
</div>
</div>
</div>
</div>
</div>
</div>
</
template
>
</
template
>
...
@@ -587,6 +537,66 @@
...
@@ -587,6 +537,66 @@
/>
/>
</div>
</div>
</AppLayout>
</AppLayout>
<!-- Tooltip Portal -->
<Teleport
to=
"body"
>
<div
v-if=
"tooltipVisible"
class=
"fixed z-[9999] pointer-events-none -translate-y-1/2"
:style=
"{
left: tooltipPosition.x + 'px',
top: tooltipPosition.y + 'px'
}"
>
<div
class=
"whitespace-nowrap rounded-lg border border-gray-700 bg-gray-900 px-3 py-2.5 text-xs text-white shadow-xl dark:border-gray-600 dark:bg-gray-800"
>
<div
class=
"space-y-1.5"
>
<!-- Cost Breakdown -->
<div
class=
"mb-2 border-b border-gray-700 pb-1.5"
>
<div
class=
"text-xs font-semibold text-gray-300 mb-1"
>
成本明细
</div>
<div
v-if=
"tooltipData && tooltipData.input_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{ t('admin.usage.inputCost') }}
</span>
<span
class=
"font-medium text-white"
>
${{ tooltipData.input_cost.toFixed(6) }}
</span>
</div>
<div
v-if=
"tooltipData && tooltipData.output_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{ t('admin.usage.outputCost') }}
</span>
<span
class=
"font-medium text-white"
>
${{ tooltipData.output_cost.toFixed(6) }}
</span>
</div>
<div
v-if=
"tooltipData && tooltipData.cache_creation_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{ t('admin.usage.cacheCreationCost') }}
</span>
<span
class=
"font-medium text-white"
>
${{ tooltipData.cache_creation_cost.toFixed(6) }}
</span>
</div>
<div
v-if=
"tooltipData && tooltipData.cache_read_cost > 0"
class=
"flex items-center justify-between gap-4"
>
<span
class=
"text-gray-400"
>
{{ t('admin.usage.cacheReadCost') }}
</span>
<span
class=
"font-medium text-white"
>
${{ tooltipData.cache_read_cost.toFixed(6) }}
</span>
</div>
</div>
<!-- Rate and Summary -->
<div
class=
"flex items-center justify-between gap-6"
>
<span
class=
"text-gray-400"
>
{{ t('usage.rate') }}
</span>
<span
class=
"font-semibold text-blue-400"
>
{{ (tooltipData?.rate_multiplier || 1).toFixed(2) }}x
</span
>
</div>
<div
class=
"flex items-center justify-between gap-6"
>
<span
class=
"text-gray-400"
>
{{ t('usage.original') }}
</span>
<span
class=
"font-medium text-white"
>
${{ tooltipData?.total_cost.toFixed(6) }}
</span>
</div>
<div
class=
"flex items-center justify-between gap-6 border-t border-gray-700 pt-1.5"
>
<span
class=
"text-gray-400"
>
{{ t('usage.billed') }}
</span>
<span
class=
"font-semibold text-green-400"
>
${{ tooltipData?.actual_cost.toFixed(6) }}
</span
>
</div>
</div>
<!-- Tooltip Arrow (left side) -->
<div
class=
"absolute right-full top-1/2 h-0 w-0 -translate-y-1/2 border-b-[6px] border-r-[6px] border-t-[6px] border-b-transparent border-r-gray-900 border-t-transparent dark:border-r-gray-800"
></div>
</div>
</div>
</Teleport>
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
...
@@ -615,6 +625,11 @@ import type {
...
@@ -615,6 +625,11 @@ import type {
const
{
t
}
=
useI18n
()
const
{
t
}
=
useI18n
()
const
appStore
=
useAppStore
()
const
appStore
=
useAppStore
()
// Tooltip state
const
tooltipVisible
=
ref
(
false
)
const
tooltipPosition
=
ref
({
x
:
0
,
y
:
0
})
const
tooltipData
=
ref
<
UsageLog
|
null
>
(
null
)
// Usage stats from API
// Usage stats from API
const
usageStats
=
ref
<
AdminUsageStatsResponse
|
null
>
(
null
)
const
usageStats
=
ref
<
AdminUsageStatsResponse
|
null
>
(
null
)
...
@@ -1038,6 +1053,22 @@ const handleClickOutside = (event: MouseEvent) => {
...
@@ -1038,6 +1053,22 @@ const handleClickOutside = (event: MouseEvent) => {
}
}
}
}
// Tooltip functions
const
showTooltip
=
(
event
:
MouseEvent
,
row
:
UsageLog
)
=>
{
const
target
=
event
.
currentTarget
as
HTMLElement
const
rect
=
target
.
getBoundingClientRect
()
tooltipData
.
value
=
row
tooltipPosition
.
value
.
x
=
rect
.
right
+
8
tooltipPosition
.
value
.
y
=
rect
.
top
+
rect
.
height
/
2
tooltipVisible
.
value
=
true
}
const
hideTooltip
=
()
=>
{
tooltipVisible
.
value
=
false
tooltipData
.
value
=
null
}
onMounted
(()
=>
{
onMounted
(()
=>
{
initializeDateRange
()
initializeDateRange
()
loadFilterOptions
()
loadFilterOptions
()
...
...
frontend/src/views/admin/UsersView.vue
View file @
7a0de176
...
@@ -203,8 +203,7 @@
...
@@ -203,8 +203,7 @@
<!-- 主要操作:编辑和删除(始终显示) -->
<!-- 主要操作:编辑和删除(始终显示) -->
<button
<button
@
click=
"handleEdit(row)"
@
click=
"handleEdit(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-primary-600 dark:hover:bg-dark-700 dark:hover:text-primary-400"
:title=
"t('common.edit')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -219,12 +218,12 @@
...
@@ -219,12 +218,12 @@
d=
"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
d=
"M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
common.edit
'
)
}}
</span>
</button>
</button>
<button
<button
v-if=
"row.role !== 'admin'"
v-if=
"row.role !== 'admin'"
@
click=
"handleDelete(row)"
@
click=
"handleDelete(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
:title=
"t('common.delete')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -239,6 +238,7 @@
...
@@ -239,6 +238,7 @@
d=
"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
d=
"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
common.delete
'
)
}}
</span>
</button>
</button>
<!-- 次要操作:展开时显示 -->
<!-- 次要操作:展开时显示 -->
...
@@ -248,16 +248,11 @@
...
@@ -248,16 +248,11 @@
v-if=
"row.role !== 'admin'"
v-if=
"row.role !== 'admin'"
@
click=
"handleToggleStatus(row)"
@
click=
"handleToggleStatus(row)"
:class=
"[
:class=
"[
'rounded-lg p-
2
transition-colors',
'
flex flex-col items-center gap-0.5
rounded-lg p-
1.5
transition-colors',
row.status === 'active'
row.status === 'active'
? 'text-gray-500 hover:bg-orange-50 hover:text-orange-600 dark:hover:bg-orange-900/20 dark:hover:text-orange-400'
? 'text-gray-500 hover:bg-orange-50 hover:text-orange-600 dark:hover:bg-orange-900/20 dark:hover:text-orange-400'
: 'text-gray-500 hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400'
: 'text-gray-500 hover:bg-green-50 hover:text-green-600 dark:hover:bg-green-900/20 dark:hover:text-green-400'
]"
]"
:title=
"
row.status === 'active'
? t('admin.users.disableUser')
: t('admin.users.enableUser')
"
>
>
<svg
<svg
v-if=
"row.status === 'active'"
v-if=
"row.status === 'active'"
...
@@ -287,12 +282,12 @@
...
@@ -287,12 +282,12 @@
d=
"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
d=
"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
row
.
status
===
'
active
'
?
t
(
'
admin.users.disable
'
)
:
t
(
'
admin.users.enable
'
)
}}
</span>
</button>
</button>
<!-- Allowed Groups -->
<!-- Allowed Groups -->
<button
<button
@
click=
"handleAllowedGroups(row)"
@
click=
"handleAllowedGroups(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-blue-50 hover:text-blue-600 dark:hover:bg-blue-900/20 dark:hover:text-blue-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-blue-50 hover:text-blue-600 dark:hover:bg-blue-900/20 dark:hover:text-blue-400"
:title=
"t('admin.users.setAllowedGroups')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -307,12 +302,12 @@
...
@@ -307,12 +302,12 @@
d=
"M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"
d=
"M18 18.72a9.094 9.094 0 003.741-.479 3 3 0 00-4.682-2.72m.94 3.198l.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0112 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 016 18.719m12 0a5.971 5.971 0 00-.941-3.197m0 0A5.995 5.995 0 0012 12.75a5.995 5.995 0 00-5.058 2.772m0 0a3 3 0 00-4.681 2.72 8.986 8.986 0 003.74.477m.94-3.197a5.971 5.971 0 00-.94 3.197M15 6.75a3 3 0 11-6 0 3 3 0 016 0zm6 3a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0zm-13.5 0a2.25 2.25 0 11-4.5 0 2.25 2.25 0 014.5 0z"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
admin.users.groups
'
)
}}
</span>
</button>
</button>
<!-- View API Keys -->
<!-- View API Keys -->
<button
<button
@
click=
"handleViewApiKeys(row)"
@
click=
"handleViewApiKeys(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-purple-50 hover:text-purple-600 dark:hover:bg-purple-900/20 dark:hover:text-purple-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-purple-50 hover:text-purple-600 dark:hover:bg-purple-900/20 dark:hover:text-purple-400"
:title=
"t('admin.users.viewApiKeys')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -324,15 +319,15 @@
...
@@ -324,15 +319,15 @@
<path
<path
stroke-linecap=
"round"
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-linejoin=
"round"
d=
"M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1
2
21.75 8.25z"
d=
"M15.75 5.25a3 3 0 013 3m3 0a6 6 0 01-7.029 5.912c-.563-.097-1.159.026-1.563.43L10.5 17.25H8.25v2.25H6v2.25H2.25v-2.818c0-.597.237-1.17.659-1.591l6.499-6.499c.404-.404.527-1 .43-1.563A6 6 0 1
1
21.75 8.25z"
/>
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
admin.users.apiKeys
'
)
}}
</span>
</button>
</button>
<!-- Deposit -->
<!-- Deposit -->
<button
<button
@
click=
"handleDeposit(row)"
@
click=
"handleDeposit(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-emerald-50 hover:text-emerald-600 dark:hover:bg-emerald-900/20 dark:hover:text-emerald-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-emerald-50 hover:text-emerald-600 dark:hover:bg-emerald-900/20 dark:hover:text-emerald-400"
:title=
"t('admin.users.deposit')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -343,12 +338,12 @@
...
@@ -343,12 +338,12 @@
>
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
d=
"M12 4.5v15m7.5-7.5h-15"
/>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
d=
"M12 4.5v15m7.5-7.5h-15"
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
admin.users.deposit
'
)
}}
</span>
</button>
</button>
<!-- Withdraw -->
<!-- Withdraw -->
<button
<button
@
click=
"handleWithdraw(row)"
@
click=
"handleWithdraw(row)"
class=
"rounded-lg p-2 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
class=
"flex flex-col items-center gap-0.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-red-50 hover:text-red-600 dark:hover:bg-red-900/20 dark:hover:text-red-400"
:title=
"t('admin.users.withdraw')"
>
>
<svg
<svg
class=
"h-4 w-4"
class=
"h-4 w-4"
...
@@ -359,6 +354,7 @@
...
@@ -359,6 +354,7 @@
>
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
d=
"M5 12h14"
/>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
d=
"M5 12h14"
/>
</svg>
</svg>
<span
class=
"text-xs"
>
{{
t
(
'
admin.users.withdraw
'
)
}}
</span>
</button>
</button>
</
template
>
</
template
>
</div>
</div>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment