Compare commits
No commits in common. "main" and "khj" have entirely different histories.
@ -14,7 +14,7 @@
|
|||||||
:value="computedValue"
|
:value="computedValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:maxLength="maxlength"
|
:maxLength="maxlength"
|
||||||
:placeholder="placeholder ? placeholder : title"
|
:placeholder="title"
|
||||||
@blur="$emit('blur')"
|
@blur="$emit('blur')"
|
||||||
/>
|
/>
|
||||||
<span class="input-group-text">@ localhost.co.kr</span>
|
<span class="input-group-text">@ localhost.co.kr</span>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
:value="computedValue"
|
:value="computedValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:maxLength="maxlength"
|
:maxLength="maxlength"
|
||||||
:placeholder="placeholder ? placeholder : title"
|
:placeholder="title"
|
||||||
@blur="$emit('blur')"
|
@blur="$emit('blur')"
|
||||||
@click="handleDateClick"
|
@click="handleDateClick"
|
||||||
ref="inputElement"
|
ref="inputElement"
|
||||||
@ -89,10 +89,6 @@
|
|||||||
default: false,
|
default: false,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const emits = defineEmits(['update:data', 'update:alert', 'blur']);
|
const emits = defineEmits(['update:data', 'update:alert', 'blur']);
|
||||||
|
|||||||
@ -80,12 +80,12 @@
|
|||||||
<div class="text-truncate">Authorization</div>
|
<div class="text-truncate">Authorization</div>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</li>
|
</li>
|
||||||
<li class="menu-item" :class="$route.path.includes('/people') ? 'active' : ''">
|
<!-- <li class="menu-item" :class="$route.path.includes('/sample') ? 'active' : ''">
|
||||||
<RouterLink class="menu-link" to="/people"> <i class="bi "></i>
|
<RouterLink class="menu-link" to="/sample"> <i class="bi "></i>
|
||||||
<i class="menu-icon icon-base bi bi-people-fill"></i>
|
<i class="menu-icon tf-icons bx bx-calendar"></i>
|
||||||
<div class="text-truncate">people</div>
|
<div class="text-truncate">Sample</div>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
</li>
|
</li> -->
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
<!-- / Menu -->
|
<!-- / Menu -->
|
||||||
@ -94,7 +94,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { useUserInfoStore } from '@s/useUserInfoStore';
|
import { useUserInfoStore } from '@s/useUserInfoStore';
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
|
||||||
|
|
||||||
const userStore = useUserInfoStore();
|
const userStore = useUserInfoStore();
|
||||||
const allowedUserId = 1; // 특정 ID (변경필요!!)
|
const allowedUserId = 1; // 특정 ID (변경필요!!)
|
||||||
|
|||||||
@ -109,12 +109,6 @@ const routes = [
|
|||||||
component: () => import('@v/admin/TheAuthorization.vue'),
|
component: () => import('@v/admin/TheAuthorization.vue'),
|
||||||
meta: { requiresAuth: true },
|
meta: { requiresAuth: true },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/people',
|
|
||||||
name: 'people',
|
|
||||||
component: () => import('@v/people/PeopleList.vue'),
|
|
||||||
meta: { requiresAuth: true },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/error/400',
|
path: '/error/400',
|
||||||
name: 'Error400',
|
name: 'Error400',
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<!-- 프로필 사진 -->
|
<!-- 프로필 사진 -->
|
||||||
<img
|
<img
|
||||||
:src="getProfileImage(user.photo)"
|
:src="getProfileImage(user.photo)"
|
||||||
class="user-avatar2"
|
class="profile-img"
|
||||||
alt="프로필 사진"
|
alt="프로필 사진"
|
||||||
@error="setDefaultImage"
|
@error="setDefaultImage"
|
||||||
/>
|
/>
|
||||||
@ -107,14 +107,4 @@ onMounted(fetchUsers);
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.user-avatar2 {
|
|
||||||
width: 160px;
|
|
||||||
height: 200px;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: block;
|
|
||||||
margin: 1rem auto 0 auto;
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -65,7 +65,7 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- 기존 비밀번호 입력 -->
|
<!-- 기존 비밀번호 입력 -->
|
||||||
<UserFormInput title="비밀번호 재설정" placeholder="기존 비밀번호를 입력하세요" name="currentPw" type="password"
|
<UserFormInput title="비밀번호 재설정" name="currentPw" type="password"
|
||||||
:value="password.current" @update:data="password.current = $event"
|
:value="password.current" @update:data="password.current = $event"
|
||||||
@blur="checkCurrentPassword" @keypress="noSpace" />
|
@blur="checkCurrentPassword" @keypress="noSpace" />
|
||||||
<span v-if="passwordError" class="text-danger invalid-feedback mt-1 d-block">
|
<span v-if="passwordError" class="text-danger invalid-feedback mt-1 d-block">
|
||||||
|
|||||||
@ -1,318 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="container-xxl flex-grow-1 container-p-y">
|
|
||||||
<div class="card">
|
|
||||||
<!-- 사원 목록이 없을 경우 표시 -->
|
|
||||||
<div v-if="allUserList.length === 0" class="text-center my-4">
|
|
||||||
<p class="text-muted">등록된 사원이 없습니다.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 사원 카드 리스트 영역 -->
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="card-list">
|
|
||||||
<div
|
|
||||||
v-for="(person, index) in allUserList"
|
|
||||||
:key="index"
|
|
||||||
class="person-card"
|
|
||||||
@click="openModal(person)"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<img
|
|
||||||
class="rounded-circle user-avatar pointer"
|
|
||||||
:src="getProfileImage(person.MEMBERPRF)"
|
|
||||||
:style="{ borderColor: person.usercolor }"
|
|
||||||
@error="setDefaultImage"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<h3 class="person-name">{{ person.MEMBERNAM }}</h3>
|
|
||||||
<p class="person-email">{{ person.MEMBERIDS }}@local-host.co.kr</p>
|
|
||||||
<p class="person-phone">{{ person.MEMBERTEL }}</p>
|
|
||||||
<small>
|
|
||||||
{{ person.MEMBERARR }} {{ person.MEMBERDTL }}
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 상세보기 Modal -->
|
|
||||||
<div v-if="showModal" class="modal-overlay" @click.self="closeModal">
|
|
||||||
<div class="modal-content">
|
|
||||||
<button class="close-btn" @click="closeModal">×</button>
|
|
||||||
<div class="modal-body">
|
|
||||||
<img
|
|
||||||
class="user-avatar2"
|
|
||||||
:src="getProfileImage(selectedPerson.MEMBERPRF)"
|
|
||||||
:style="{ borderColor: selectedPerson.usercolor }"
|
|
||||||
@error="setDefaultImage"
|
|
||||||
/>
|
|
||||||
<h4>{{ selectedPerson.MEMBERNAM }}</h4>
|
|
||||||
<p>{{ selectedPerson.MEMBERIDS }}@local-host.co.kr</p>
|
|
||||||
<p>{{ selectedPerson.MEMBERTEL }}</p>
|
|
||||||
<p>{{ selectedPerson.MEMBERARR }} {{ selectedPerson.MEMBERDTL }}</p>
|
|
||||||
<hr />
|
|
||||||
<!-- 추가 정보: 사용자가 속한 프로젝트 목록 -->
|
|
||||||
<h5>참여 프로젝트</h5>
|
|
||||||
<div v-if="memberProjects.length > 0" class="project-list-container">
|
|
||||||
<ul>
|
|
||||||
<li
|
|
||||||
v-for="(project, idx) in memberProjects"
|
|
||||||
:key="idx"
|
|
||||||
class="project-item"
|
|
||||||
>
|
|
||||||
<span class="project-name">{{ project.PROJCTNAM }}</span>
|
|
||||||
<span class="project-period">
|
|
||||||
<!-- projectEndDate가 있는 경우 -->
|
|
||||||
<!-- <template v-if="project.projectEndDate"> -->
|
|
||||||
{{ project.userStartDate ? project.userStartDate : project.projectStartDate }} ~
|
|
||||||
{{ project.userEndDate ? project.userEndDate : project.projectEndDate }}
|
|
||||||
<!-- </template> -->
|
|
||||||
<!-- 없으면 종료일 표시 안함 -->
|
|
||||||
<!-- <template v-else>
|
|
||||||
{{ project.userStartDate ? project.userStartDate : project.projectStartDate }} ~
|
|
||||||
</template> -->
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<p>참여중인 프로젝트가 없습니다.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from '@api' // API 호출용 Axios 인스턴스
|
|
||||||
import { ref, onMounted } from 'vue'
|
|
||||||
import SearchBar from '@c/search/SearchBar.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'PeopleList',
|
|
||||||
components: { SearchBar },
|
|
||||||
setup() {
|
|
||||||
const allUserList = ref([]) // 전체 사원 목록
|
|
||||||
const user = ref({}) // 현재 로그인한 사용자 (필요 시 사용)
|
|
||||||
const showModal = ref(false) // 모달 표시 여부
|
|
||||||
const selectedPerson = ref({})// 모달에 표시할 선택된 사원 정보
|
|
||||||
const memberProjects = ref([])// 선택된 사원의 프로젝트 목록
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
try {
|
|
||||||
const response = await axios.get('user/allUserList')
|
|
||||||
allUserList.value = response.data.data.allUserList
|
|
||||||
user.value = response.data.data.user
|
|
||||||
} catch (error) {
|
|
||||||
console.error('사원 목록 조회 실패:', error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const baseUrl = axios.defaults.baseURL.replace(/api\/$/, '')
|
|
||||||
const defaultProfile = '/img/icons/icon.png'
|
|
||||||
|
|
||||||
const getProfileImage = (profilePath) => {
|
|
||||||
return profilePath && profilePath.trim()
|
|
||||||
? `${baseUrl}upload/img/profile/${profilePath}`
|
|
||||||
: defaultProfile
|
|
||||||
}
|
|
||||||
|
|
||||||
const setDefaultImage = (event) => {
|
|
||||||
event.target.src = defaultProfile
|
|
||||||
}
|
|
||||||
|
|
||||||
// 참여 프로젝트 조회 API
|
|
||||||
const fetchMemberProjects = async (memberSeq) => {
|
|
||||||
try {
|
|
||||||
const res = await axios.get(`project/people/${memberSeq}`)
|
|
||||||
memberProjects.value = res.data.data
|
|
||||||
} catch (error) {
|
|
||||||
console.error('프로젝트 조회 실패:', error)
|
|
||||||
memberProjects.value = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const openModal = (person) => {
|
|
||||||
selectedPerson.value = person
|
|
||||||
fetchMemberProjects(person.MEMBERSEQ)
|
|
||||||
showModal.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const closeModal = () => {
|
|
||||||
showModal.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
allUserList,
|
|
||||||
user,
|
|
||||||
showModal,
|
|
||||||
selectedPerson,
|
|
||||||
memberProjects,
|
|
||||||
openModal,
|
|
||||||
closeModal,
|
|
||||||
getProfileImage,
|
|
||||||
defaultProfile,
|
|
||||||
setDefaultImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.container-xxl {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 1rem;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-card {
|
|
||||||
width: 280px;
|
|
||||||
border: 1px solid #eee;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
background: #fff;
|
|
||||||
transition: box-shadow 0.2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-card:hover {
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-card .card-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 120px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
background: #f8f9fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-avatar {
|
|
||||||
width: 160px;
|
|
||||||
height: 200px;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: 2px solid #ddd;
|
|
||||||
display: block;
|
|
||||||
margin: 1rem auto 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-avatar2 {
|
|
||||||
width: 160px;
|
|
||||||
height: 200px;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: block;
|
|
||||||
margin: 1rem auto 0 auto;
|
|
||||||
margin-top: 0px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-card .card-body {
|
|
||||||
padding: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-name {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.person-email,
|
|
||||||
.person-phone {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 모달 스타일 */
|
|
||||||
.modal-overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 111%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
z-index: 999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
position: relative;
|
|
||||||
width: 400px;
|
|
||||||
background: #fff;
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
animation: slideDown 0.3s ease forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-btn {
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
position: absolute;
|
|
||||||
top: 0.5rem;
|
|
||||||
right: 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-img {
|
|
||||||
width: 50%;
|
|
||||||
height: 50%;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 프로젝트 리스트 스타일 */
|
|
||||||
.project-list-container {
|
|
||||||
max-height: 200px; /* 필요에 따라 높이 조절 */
|
|
||||||
overflow-y: auto;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
list-style: none;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 0.25rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-name {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.project-period {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: #888;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slideDown {
|
|
||||||
0% {
|
|
||||||
transform: translateY(-15%);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in New Issue
Block a user