173 lines
5.9 KiB
Vue
173 lines
5.9 KiB
Vue
<template>
|
|
<div>
|
|
<AppHeader />
|
|
|
|
<div class="container-fluid py-4">
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<h4 class="mb-0">
|
|
<i class="bi bi-tools me-2"></i>유지보수 업무 등록
|
|
</h4>
|
|
<NuxtLink to="/maintenance" class="btn btn-outline-secondary">
|
|
<i class="bi bi-arrow-left me-1"></i>목록
|
|
</NuxtLink>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<label class="form-label">프로젝트</label>
|
|
<select class="form-select" v-model="form.projectId">
|
|
<option value="">선택 안함</option>
|
|
<option v-for="p in projects" :key="p.projectId" :value="p.projectId">
|
|
{{ p.projectName }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label">요청일 <span class="text-danger">*</span></label>
|
|
<input type="date" class="form-control" v-model="form.requestDate" />
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label">담당자</label>
|
|
<select class="form-select" v-model="form.assigneeId">
|
|
<option value="">미배정</option>
|
|
<option v-for="e in employees" :key="e.employeeId" :value="e.employeeId">
|
|
{{ e.employeeName }}
|
|
</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-8">
|
|
<label class="form-label">제목 <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" v-model="form.requestTitle" placeholder="업무 제목" />
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="form-label">우선순위</label>
|
|
<select class="form-select" v-model="form.priority">
|
|
<option value="HIGH">높음</option>
|
|
<option value="MEDIUM">보통</option>
|
|
<option value="LOW">낮음</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-2">
|
|
<label class="form-label">업무유형</label>
|
|
<select class="form-select" v-model="form.taskType">
|
|
<option value="GENERAL">일반</option>
|
|
<option value="BUG">버그수정</option>
|
|
<option value="ENHANCEMENT">기능개선</option>
|
|
<option value="DATA">데이터</option>
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">요청자명</label>
|
|
<input type="text" class="form-control" v-model="form.requesterName" placeholder="요청자 이름" />
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label">요청자 연락처</label>
|
|
<input type="text" class="form-control" v-model="form.requesterContact" placeholder="전화번호 또는 이메일" />
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label">내용</label>
|
|
<textarea class="form-control" v-model="form.requestContent" rows="6" placeholder="업무 내용을 입력하세요"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card-footer text-end">
|
|
<button class="btn btn-primary" @click="save" :disabled="isSaving">
|
|
<span v-if="isSaving">
|
|
<span class="spinner-border spinner-border-sm me-1"></span>등록 중...
|
|
</span>
|
|
<span v-else><i class="bi bi-check-lg me-1"></i>등록</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const { fetchCurrentUser } = useAuth()
|
|
const router = useRouter()
|
|
|
|
interface Project { projectId: number; projectName: string }
|
|
interface Employee { employeeId: number; employeeName: string }
|
|
|
|
const projects = ref<Project[]>([])
|
|
const employees = ref<Employee[]>([])
|
|
const isSaving = ref(false)
|
|
|
|
const form = ref({
|
|
projectId: '',
|
|
requestDate: new Date().toISOString().split('T')[0],
|
|
requestTitle: '',
|
|
requestContent: '',
|
|
requesterName: '',
|
|
requesterContact: '',
|
|
taskType: 'GENERAL',
|
|
priority: 'MEDIUM',
|
|
assigneeId: ''
|
|
})
|
|
|
|
onMounted(async () => {
|
|
const user = await fetchCurrentUser()
|
|
if (!user) {
|
|
router.push('/login')
|
|
return
|
|
}
|
|
await loadProjects()
|
|
await loadEmployees()
|
|
})
|
|
|
|
async function loadProjects() {
|
|
try {
|
|
const res = await $fetch<{ projects: Project[] }>('/api/project/list')
|
|
projects.value = res.projects || []
|
|
} catch (e) {
|
|
console.error('Load projects error:', e)
|
|
}
|
|
}
|
|
|
|
async function loadEmployees() {
|
|
try {
|
|
const res = await $fetch<{ employees: Employee[] }>('/api/employee/list')
|
|
employees.value = res.employees || []
|
|
} catch (e) {
|
|
console.error('Load employees error:', e)
|
|
}
|
|
}
|
|
|
|
async function save() {
|
|
if (!form.value.requestTitle) {
|
|
alert('제목을 입력하세요.')
|
|
return
|
|
}
|
|
if (!form.value.requestDate) {
|
|
alert('요청일을 선택하세요.')
|
|
return
|
|
}
|
|
|
|
isSaving.value = true
|
|
try {
|
|
const res = await $fetch<{ taskId: number }>('/api/maintenance/create', {
|
|
method: 'POST',
|
|
body: {
|
|
projectId: form.value.projectId ? Number(form.value.projectId) : null,
|
|
requestDate: form.value.requestDate,
|
|
requestTitle: form.value.requestTitle,
|
|
requestContent: form.value.requestContent,
|
|
requesterName: form.value.requesterName,
|
|
requesterContact: form.value.requesterContact,
|
|
taskType: form.value.taskType,
|
|
priority: form.value.priority,
|
|
assigneeId: form.value.assigneeId ? Number(form.value.assigneeId) : null
|
|
}
|
|
})
|
|
router.push(`/maintenance/${res.taskId}`)
|
|
} catch (e: any) {
|
|
alert(e.data?.message || e.message || '등록에 실패했습니다.')
|
|
} finally {
|
|
isSaving.value = false
|
|
}
|
|
}
|
|
</script>
|