feat: improve login UX and add admin login lock reset
- Translate all login error messages to Chinese (network errors, HTTP status codes, URL validation errors) - Add password visibility toggle (eye icon) to login form - Add live countdown timer when login is locked, disable login button during cooldown, auto-clear error when countdown ends - Add X button red hover feedback in server settings dialog - Add LoginGuard.Unlock() method to clear Redis lock/failure keys - Expose POST /admin-users/:id/reset-login-lock endpoint in ops API - Add "重置登录保护" button in ops-web user management table Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,18 @@
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip title="重置登录保护">
|
||||
<a-popconfirm
|
||||
title="确认清除该用户的登录锁定状态?"
|
||||
:ok-button-props="{ loading: resetLoginLockLoadingId === record.id }"
|
||||
@confirm="resetLoginLock(record)"
|
||||
>
|
||||
<a-button type="text" shape="circle" size="small" class="action-btn action-unlock">
|
||||
<UnlockOutlined />
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip :title="record.status === 'active' ? '停用用户' : '启用用户'">
|
||||
<a-popconfirm
|
||||
:title="record.status === 'active' ? '确认停用该用户?' : '确认启用该用户?'"
|
||||
@@ -283,6 +295,7 @@ import {
|
||||
PlayCircleOutlined,
|
||||
ReloadOutlined,
|
||||
StopOutlined,
|
||||
UnlockOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
import type { TableColumnsType, TablePaginationConfig } from 'ant-design-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
@@ -608,6 +621,20 @@ async function resetPlanUsage(row: AdminUserRow) {
|
||||
}
|
||||
}
|
||||
|
||||
const resetLoginLockLoadingId = ref<number | null>(null)
|
||||
|
||||
async function resetLoginLock(row: AdminUserRow) {
|
||||
resetLoginLockLoadingId.value = row.id
|
||||
try {
|
||||
await http.post(`/admin-users/${row.id}/reset-login-lock`)
|
||||
message.success('登录保护已重置,用户可立即重新登录')
|
||||
} catch (error) {
|
||||
if (error instanceof OpsApiError) message.error(error.detail || error.message)
|
||||
} finally {
|
||||
resetLoginLockLoadingId.value = null
|
||||
}
|
||||
}
|
||||
|
||||
const resetOpen = ref(false)
|
||||
const resetLoading = ref(false)
|
||||
const resetTarget = ref<AdminUserRow | null>(null)
|
||||
@@ -806,4 +833,8 @@ onMounted(() => {
|
||||
color: #94a3b8;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.action-unlock :deep(.anticon) {
|
||||
color: #16a34a;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user