기능검증 중

This commit is contained in:
2026-01-11 12:59:21 +09:00
parent d4620dc1fa
commit 1f9745fdfc
14 changed files with 2000 additions and 88 deletions

View File

@@ -185,6 +185,64 @@
</div>
</div>
<!-- 계정 관리 -->
<div class="card mb-4">
<div class="card-header">
<strong><i class="bi bi-key me-2"></i>계정 관리</strong>
</div>
<div class="card-body">
<!-- Google 연결 상태 -->
<div class="row mb-3 align-items-center">
<div class="col-3 text-muted">Google 연결</div>
<div class="col-9">
<span v-if="userInfo.googleId" class="badge bg-success me-2">
<i class="bi bi-check-circle me-1"></i>연결됨
</span>
<span v-if="userInfo.googleEmail" class="text-muted small">{{ userInfo.googleEmail }}</span>
<span v-if="!userInfo.googleId" class="badge bg-secondary">미연결</span>
<button
v-if="userInfo.googleId && !isSelf"
class="btn btn-sm btn-outline-warning ms-2"
@click="unlinkGoogle"
:disabled="isUnlinking"
>
<span v-if="isUnlinking" class="spinner-border spinner-border-sm me-1"></span>
연결 해제
</button>
</div>
</div>
<!-- 비밀번호 상태 -->
<div class="row mb-3 align-items-center">
<div class="col-3 text-muted">비밀번호</div>
<div class="col-9">
<span v-if="userInfo.hasPassword" class="badge bg-success me-2">
<i class="bi bi-check-circle me-1"></i>설정됨
</span>
<span v-else class="badge bg-warning text-dark me-2">미설정</span>
<button
v-if="!isSelf"
class="btn btn-sm btn-outline-danger"
@click="resetPassword"
:disabled="isResetting"
>
<span v-if="isResetting" class="spinner-border spinner-border-sm me-1"></span>
비밀번호 초기화
</button>
</div>
</div>
<!-- 마지막 로그인 -->
<div class="row align-items-center">
<div class="col-3 text-muted">마지막 로그인</div>
<div class="col-9">
{{ userInfo.lastLoginAt ? formatDateTime(userInfo.lastLoginAt) : '없음' }}
<code v-if="userInfo.lastLoginIp" class="ms-2">{{ userInfo.lastLoginIp }}</code>
</div>
</div>
</div>
</div>
<!-- 위험 영역 -->
<div class="card border-danger" v-if="!isSelf">
<div class="card-header bg-danger text-white">
@@ -236,6 +294,8 @@ const employeeId = computed(() => route.params.id as string)
const isLoading = ref(true)
const isSaving = ref(false)
const isDeleting = ref(false)
const isResetting = ref(false)
const isUnlinking = ref(false)
const showDeleteModal = ref(false)
const currentUser = ref<any>(null)
const userInfo = ref<any>(null)
@@ -345,6 +405,45 @@ async function deleteUser() {
}
}
async function resetPassword() {
if (!confirm('비밀번호를 초기화하시겠습니까?\n임시 비밀번호가 생성되어 화면에 표시됩니다.')) return
isResetting.value = true
try {
const res = await $fetch<any>(`/api/admin/user/reset-password`, {
method: 'POST',
body: { employeeId: parseInt(employeeId.value) }
})
alert(`비밀번호가 초기화되었습니다.\n\n임시 비밀번호: ${res.tempPassword}\n\n사용자에게 전달해주세요.`)
await loadUserInfo()
} catch (e: any) {
console.error(e)
alert(e.data?.message || '비밀번호 초기화에 실패했습니다.')
} finally {
isResetting.value = false
}
}
async function unlinkGoogle() {
if (!confirm('Google 계정 연결을 해제하시겠습니까?')) return
isUnlinking.value = true
try {
await $fetch(`/api/employee/${employeeId.value}/unlink-google`, {
method: 'POST'
})
alert('Google 계정 연결이 해제되었습니다.')
await loadUserInfo()
} catch (e: any) {
console.error(e)
alert(e.data?.message || 'Google 연결 해제에 실패했습니다.')
} finally {
isUnlinking.value = false
}
}
function formatDateTime(dateStr: string) {
if (!dateStr) return '-'
const d = new Date(dateStr)