Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-front
All checks were successful
LocalNet_front/pipeline/head This commit looks good
All checks were successful
LocalNet_front/pipeline/head This commit looks good
This commit is contained in:
commit
aa22023ca3
@ -7,7 +7,6 @@
|
|||||||
/* board */
|
/* board */
|
||||||
.board-content img {
|
.board-content img {
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
width: 100% !important;
|
|
||||||
height: auto !important;
|
height: auto !important;
|
||||||
display: block;
|
display: block;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
@ -520,6 +519,24 @@
|
|||||||
|
|
||||||
/* project list */
|
/* project list */
|
||||||
|
|
||||||
|
.hidden-start-input {
|
||||||
|
position: absolute;
|
||||||
|
top: 103%;
|
||||||
|
left: 20%;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-end-input {
|
||||||
|
position: absolute;
|
||||||
|
top: 113.3%;
|
||||||
|
left: 20%;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.map {
|
.map {
|
||||||
top: -160px;
|
top: -160px;
|
||||||
left: -5px;
|
left: -5px;
|
||||||
@ -684,73 +701,83 @@
|
|||||||
|
|
||||||
/* BoardComment end */
|
/* BoardComment end */
|
||||||
|
|
||||||
|
/* vote */
|
||||||
|
.hidden-date-input {
|
||||||
|
position: absolute;
|
||||||
|
top: 31.5%;
|
||||||
|
left: 17%;
|
||||||
|
width: 100%;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* 권한부여 */
|
/* 권한부여 */
|
||||||
.user-card-container {
|
.user-card-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.user-card {
|
.user-card {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.profile-img {
|
.profile-img {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.switch {
|
.switch {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
.switch input {
|
.switch input {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
.slider {
|
.slider {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
}
|
}
|
||||||
.slider:before {
|
.slider:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "";
|
content: "";
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
bottom: 3px;
|
bottom: 3px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
input:checked + .slider {
|
input:checked + .slider {
|
||||||
background-color: #4CAF50;
|
background-color: #4CAF50;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked + .slider:before {
|
input:checked + .slider:before {
|
||||||
transform: translateX(24px);
|
transform: translateX(24px);
|
||||||
}
|
}
|
||||||
/* 권한부여 끝 */
|
/* 권한부여 끝 */
|
||||||
|
|
||||||
|
|||||||
@ -1,23 +1,10 @@
|
|||||||
/* @font-face {
|
/* 1) */
|
||||||
font-family: 'GmarketSansMedium';
|
|
||||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2001@1.1/GmarketSansMedium.woff') format('woff');
|
|
||||||
font-weight: normal;
|
|
||||||
font-style: normal;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
font-family: 'GmarketSansMedium', sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #333;
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* @font-face {
|
/* @font-face {
|
||||||
font-family: 'NanumSquareRound';
|
font-family: 'NanumSquareRound';
|
||||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_two@1.0/NanumSquareRound.woff') format('woff');
|
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_two@1.0/NanumSquareRound.woff') format('woff');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'NanumSquareRound', sans-serif;
|
font-family: 'NanumSquareRound', sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -25,13 +12,13 @@ body {
|
|||||||
color: #333;
|
color: #333;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
/* 2) */
|
||||||
/* @font-face {
|
/* @font-face {
|
||||||
font-family: 'Pretendard-Regular';
|
font-family: 'Pretendard-Regular';
|
||||||
src: url('https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff');
|
src: url('https://cdn.jsdelivr.net/gh/Project-Noonnu/noonfonts_2107@1.1/Pretendard-Regular.woff') format('woff');
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Pretendard-Regular', sans-serif;
|
font-family: 'Pretendard-Regular', sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -39,20 +26,117 @@ body {
|
|||||||
color: #333;
|
color: #333;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
/* 3) */
|
||||||
/* @font-face {
|
/* @font-face {
|
||||||
font-family: 'S-CoreDream-3Light';
|
font-family: 'NEXON Lv1 Gothic OTF';
|
||||||
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_six@1.2/S-CoreDream-3Light.woff') format('woff');
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_20-04@2.1/NEXON Lv1 Gothic OTF.woff') format('woff');
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'S-CoreDream-3Light', sans-serif;
|
font-family: 'NEXON Lv1 Gothic OTF', sans-serif;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
color: #333;
|
color: #333;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
/* 4) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'SUITE-Regular';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_2304-2@1.0/SUITE-Regular.woff2') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'SUITE-Regular', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* 5) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'GoyangIlsan';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_one@1.0/GoyangIlsan.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'GoyangIlsan', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* 6) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'GowunDodum-Regular';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_2108@1.1/GowunDodum-Regular.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'GowunDodum-Regular', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* 7) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'EASTARJET-Medium';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_231029@1.1/EASTARJET-Medium.woff2') format('woff2');
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'EASTARJET-Medium', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* 8) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'HakgyoansimChulseokbuTTF-B';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/2408-5@1.0/HakgyoansimChulseokbuTTF-B.woff2') format('woff2');
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'HakgyoansimChulseokbuTTF-B', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* 9) */
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'GongGothicMedium';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/noonfonts_20-10@1.0/GongGothicMedium.woff') format('woff');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'GongGothicMedium', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
|
|
||||||
|
/* @font-face {
|
||||||
|
font-family: 'MangoDdobak-B';
|
||||||
|
src: url('https://fastly.jsdelivr.net/gh/projectnoonnu/2405-3@1.1/MangoDdobak-B.woff2') format('woff2');
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-family: 'MangoDdobak-B', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
} */
|
||||||
|
|
||||||
/* 나눔고딕 */
|
/* 나눔고딕 */
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic&display=swap');
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
:unknown="comment.author === '익명'"
|
:unknown="comment.author === '익명'"
|
||||||
:isCommentAuthor="isCommentAuthor"
|
:isCommentAuthor="isCommentAuthor"
|
||||||
:boardId="comment.boardId"
|
:boardId="comment.boardId"
|
||||||
:profileName="comment.nickname ? comment.nickname : comment.author"
|
:profileName="displayName"
|
||||||
:date="comment.createdAt"
|
:date="comment.createdAt"
|
||||||
:comment="comment"
|
:comment="comment"
|
||||||
:profileImg="comment.profileImg"
|
:profileImg="comment.profileImg"
|
||||||
@ -76,10 +76,15 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
nickname: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
isCommentAuthor: {
|
isCommentAuthor: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
isPlusButton: {
|
isPlusButton: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@ -113,6 +118,10 @@
|
|||||||
editCommentAlert: String,
|
editCommentAlert: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const displayName = computed(() => {
|
||||||
|
return props.nickname? props.nickname: props.comment.author;
|
||||||
|
});
|
||||||
|
|
||||||
// emits 정의
|
// emits 정의
|
||||||
const emit = defineEmits([
|
const emit = defineEmits([
|
||||||
'submitComment',
|
'submitComment',
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
:isCommentAuthor="comment.isCommentAuthor"
|
:isCommentAuthor="comment.isCommentAuthor"
|
||||||
:isEditTextarea="comment.isEditTextarea"
|
:isEditTextarea="comment.isEditTextarea"
|
||||||
:isDeleted="isDeleted"
|
:isDeleted="isDeleted"
|
||||||
|
:nickname="comment.nickname"
|
||||||
:isCommentPassword="isCommentPassword"
|
:isCommentPassword="isCommentPassword"
|
||||||
:passwordCommentAlert="passwordCommentAlert || ''"
|
:passwordCommentAlert="passwordCommentAlert || ''"
|
||||||
:currentPasswordCommentId="currentPasswordCommentId"
|
:currentPasswordCommentId="currentPasswordCommentId"
|
||||||
@ -32,6 +33,7 @@
|
|||||||
:isPlusButton="false"
|
:isPlusButton="false"
|
||||||
:isLike="true"
|
:isLike="true"
|
||||||
:isCommentProfile="true"
|
:isCommentProfile="true"
|
||||||
|
:nickname="child.nickname"
|
||||||
:isCommentAuthor="child.isCommentAuthor"
|
:isCommentAuthor="child.isCommentAuthor"
|
||||||
:isCommentPassword="isCommentPassword"
|
:isCommentPassword="isCommentPassword"
|
||||||
:currentPasswordCommentId="currentPasswordCommentId"
|
:currentPasswordCommentId="currentPasswordCommentId"
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="me-2">
|
<div class="me-2">
|
||||||
<h6 class="mb-0">{{ profileName }}</h6>
|
<h6 class="mb-0">{{ profileName ? profileName : nickname }}</h6>
|
||||||
<div class="profile-detail">
|
<div class="profile-detail">
|
||||||
<span>{{ date }}</span>
|
<span>{{ date }}</span>
|
||||||
<template v-if="showDetail">
|
<template v-if="showDetail">
|
||||||
@ -62,6 +62,10 @@
|
|||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
nickname: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
unknown: {
|
unknown: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<button class="vac-btn vac-btn-warning rounded-circle d-flex align-items-center justify-content-center"
|
<button class="vac-btn vac-btn-warning rounded-circle d-flex align-items-center justify-content-center"
|
||||||
:class="{ active: halfDayType === 'AM' }"
|
:class="{ active: halfDayType === 'AM' }"
|
||||||
@click="toggleHalfDay('AM')">
|
@click="toggleHalfDay('AM')">
|
||||||
<i class="bi bi-sun"></i>
|
<i class="bi bi-sun d-flex"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<button class="vac-btn vac-btn-info rounded-circle d-flex align-items-center justify-content-center"
|
<button class="vac-btn vac-btn-info rounded-circle d-flex align-items-center justify-content-center"
|
||||||
:class="{ active: halfDayType === 'PM' }"
|
:class="{ active: halfDayType === 'PM' }"
|
||||||
@click="toggleHalfDay('PM')">
|
@click="toggleHalfDay('PM')">
|
||||||
<i class="bi bi-moon"></i>
|
<i class="bi bi-moon d-flex"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<button class="vac-btn vac-btn-primary rounded-circle d-flex align-items-center justify-content-center"
|
<button class="vac-btn vac-btn-primary rounded-circle d-flex align-items-center justify-content-center"
|
||||||
:class="{ active: halfDayType === 'FULL' }"
|
:class="{ active: halfDayType === 'FULL' }"
|
||||||
@click="toggleHalfDay('FULL')">
|
@click="toggleHalfDay('FULL')">
|
||||||
<i class="bi bi-calendar"></i>
|
<i class="bi bi-calendar d-flex"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -71,7 +71,8 @@
|
|||||||
const editor = ref(null); // 에디터 DOM 참조
|
const editor = ref(null); // 에디터 DOM 참조
|
||||||
const font = ref('nanum-gothic'); // 기본 폰트
|
const font = ref('nanum-gothic'); // 기본 폰트
|
||||||
const fontSize = ref('16px'); // 기본 폰트 크기
|
const fontSize = ref('16px'); // 기본 폰트 크기
|
||||||
const emit = defineEmits(['update:data']);
|
const emit = defineEmits(['update:data', 'update:uploadedImgList']);
|
||||||
|
const uploadedImgList = ref([]); // 에디터에 이미지 첨부시 업데이트 된 파일 인덱스 번호 리스트
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 툴바에서 선택할 수 있는 폰트 목록 설정
|
// 툴바에서 선택할 수 있는 폰트 목록 설정
|
||||||
@ -112,6 +113,13 @@
|
|||||||
quillInstance.format('size', fontSize.value);
|
quillInstance.format('size', fontSize.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 이미지 첨부 리스트가 변경 되었을때
|
||||||
|
watch(uploadedImgList, () => {
|
||||||
|
console.log(!23);
|
||||||
|
emit('update:uploadedImgList', uploadedImgList.value);
|
||||||
|
console.log('uploadedImgList.value: ', uploadedImgList.value);
|
||||||
|
});
|
||||||
|
|
||||||
// 초기 데이터가 있을 경우, HTML 형식으로 삽입
|
// 초기 데이터가 있을 경우, HTML 형식으로 삽입
|
||||||
if (props.initialData) {
|
if (props.initialData) {
|
||||||
quillInstance.setContents(JSON.parse(props.initialData));
|
quillInstance.setContents(JSON.parse(props.initialData));
|
||||||
@ -150,7 +158,15 @@
|
|||||||
|
|
||||||
// 이미지 서버에 업로드 후 URL 받기
|
// 이미지 서버에 업로드 후 URL 받기
|
||||||
uploadImageToServer(formData)
|
uploadImageToServer(formData)
|
||||||
.then(serverImageUrl => {
|
.then(data => {
|
||||||
|
const uploadImgIdx = data?.fileIndex; // 업로드 된 파일 DB 인덱스
|
||||||
|
const serverImageUrl = data?.fileUrl; // 업로드 된 파일 url
|
||||||
|
|
||||||
|
// 업로드 된 파일 인덱스 (게시글 저장 시 해당 인덱스 번호에 게시글 인덱스를 업데이트)
|
||||||
|
if (uploadImgIdx) {
|
||||||
|
uploadedImgList.value = [...uploadedImgList.value, uploadImgIdx];
|
||||||
|
}
|
||||||
|
|
||||||
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
||||||
const fullImageUrl = `${baseUrl}${serverImageUrl.replace(/\\/g, '/')}`;
|
const fullImageUrl = `${baseUrl}${serverImageUrl.replace(/\\/g, '/')}`;
|
||||||
|
|
||||||
@ -168,40 +184,40 @@
|
|||||||
|
|
||||||
// 이미지 서버 업로드
|
// 이미지 서버 업로드
|
||||||
async function uploadImageToServer(formData) {
|
async function uploadImageToServer(formData) {
|
||||||
try {
|
try {
|
||||||
// Make the POST request to upload the image
|
// Make the POST request to upload the image
|
||||||
const response = await $api.post('quilleditor/upload', formData, { isFormData: true });
|
const response = await $api.post('quilleditor/upload', formData, { isFormData: true });
|
||||||
|
|
||||||
// Check if the response contains the expected data
|
// Check if the response contains the expected data
|
||||||
if (response.data && response.data.data) {
|
if (response.data && response.data.data) {
|
||||||
const imageUrl = response.data.data;
|
const imageUrl = response.data.data;
|
||||||
return imageUrl; // Return the image URL received from the server
|
return imageUrl; // Return the image URL received from the server
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Image URL not returned from server');
|
throw new Error('Image URL not returned from server');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// Log detailed error information for debugging purposes
|
||||||
|
console.error('Image upload failed:', error);
|
||||||
|
|
||||||
|
// Handle specific error cases (e.g., network issues, authorization issues)
|
||||||
|
if (error.response) {
|
||||||
|
// If the error is from the server (e.g., 4xx or 5xx error)
|
||||||
|
console.error('Error response:', error.response.data);
|
||||||
|
toastStore.onToast('서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.', 'e');
|
||||||
|
} else if (error.request) {
|
||||||
|
// If no response is received from the server
|
||||||
|
console.error('No response received:', error.request);
|
||||||
|
toastStore.onToast('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해주세요.', 'e');
|
||||||
|
} else {
|
||||||
|
// If the error is due to something else (e.g., invalid request setup)
|
||||||
|
console.error('Error message:', error.message);
|
||||||
|
toastStore.onToast('파일 업로드 중 문제가 발생했습니다. 다시 시도해주세요.', 'e');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throw the error so the caller knows something went wrong
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
// Log detailed error information for debugging purposes
|
|
||||||
console.error('Image upload failed:', error);
|
|
||||||
|
|
||||||
// Handle specific error cases (e.g., network issues, authorization issues)
|
|
||||||
if (error.response) {
|
|
||||||
// If the error is from the server (e.g., 4xx or 5xx error)
|
|
||||||
console.error('Error response:', error.response.data);
|
|
||||||
toastStore.onToast('서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.', 'e');
|
|
||||||
} else if (error.request) {
|
|
||||||
// If no response is received from the server
|
|
||||||
console.error('No response received:', error.request);
|
|
||||||
toastStore.onToast('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해주세요.', 'e');
|
|
||||||
} else {
|
|
||||||
// If the error is due to something else (e.g., invalid request setup)
|
|
||||||
console.error('Error message:', error.message);
|
|
||||||
toastStore.onToast('파일 업로드 중 문제가 발생했습니다. 다시 시도해주세요.', 'e');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw the error so the caller knows something went wrong
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 삭제된 이미지 확인
|
// 삭제된 이미지 확인
|
||||||
function checkForDeletedImages() {
|
function checkForDeletedImages() {
|
||||||
@ -216,4 +232,3 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,9 @@
|
|||||||
@focusout="$emit('focusout', modelValue)"
|
@focusout="$emit('focusout', modelValue)"
|
||||||
@input="handleInput"
|
@input="handleInput"
|
||||||
/>
|
/>
|
||||||
|
<div v-if="isBtn" class="ms-2">
|
||||||
|
<slot name="append"></slot>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="invalid-feedback" :class="isAlert ? 'd-block' : ''">{{ title }}을 확인해주세요.</div>
|
<div class="invalid-feedback" :class="isAlert ? 'd-block' : ''">{{ title }}을 확인해주세요.</div>
|
||||||
<div class="invalid-feedback" :class="isCateAlert ? 'd-block' : ''">카테고리 중복입니다.</div>
|
<div class="invalid-feedback" :class="isCateAlert ? 'd-block' : ''">카테고리 중복입니다.</div>
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
<span :class="isEssential ? 'link-danger' : 'd-none'">*</span>
|
<span :class="isEssential ? 'link-danger' : 'd-none'">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div v-if="useInputGroup" class="input-group mb-3">
|
<div v-if="useInputGroup" class="input-group mb-1">
|
||||||
<input
|
<input
|
||||||
:id="name"
|
:id="name"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
@ -14,7 +14,6 @@
|
|||||||
:value="computedValue"
|
:value="computedValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:maxLength="maxlength"
|
:maxLength="maxlength"
|
||||||
:minLength="minlength"
|
|
||||||
:placeholder="title"
|
:placeholder="title"
|
||||||
@blur="$emit('blur')"
|
@blur="$emit('blur')"
|
||||||
/>
|
/>
|
||||||
@ -30,7 +29,6 @@
|
|||||||
:value="computedValue"
|
:value="computedValue"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:maxLength="maxlength"
|
:maxLength="maxlength"
|
||||||
:minLength="minlength"
|
|
||||||
:placeholder="title"
|
:placeholder="title"
|
||||||
@blur="$emit('blur')"
|
@blur="$emit('blur')"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -130,6 +130,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 시작일 -->
|
||||||
|
<div class="date-picker-wrapper" @click="focusStartDateInput">
|
||||||
<FormInput
|
<FormInput
|
||||||
title="시작일"
|
title="시작일"
|
||||||
type="date"
|
type="date"
|
||||||
@ -138,7 +140,11 @@
|
|||||||
:modelValue="selectedProject.PROJCTSTR"
|
:modelValue="selectedProject.PROJCTSTR"
|
||||||
@update:modelValue="selectedProject.PROJCTSTR = $event"
|
@update:modelValue="selectedProject.PROJCTSTR = $event"
|
||||||
/>
|
/>
|
||||||
|
<input ref="startDateInput" type="date" v-model="selectedProject.PROJCTSTR" class="hidden-start-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 종료일 -->
|
||||||
|
<div class="date-picker-wrapper" @click="focusEndDateInput">
|
||||||
<FormInput
|
<FormInput
|
||||||
title="종료일"
|
title="종료일"
|
||||||
type="date"
|
type="date"
|
||||||
@ -147,6 +153,8 @@
|
|||||||
:modelValue="selectedProject.PROJCTEND"
|
:modelValue="selectedProject.PROJCTEND"
|
||||||
@update:modelValue="selectedProject.PROJCTEND = $event"
|
@update:modelValue="selectedProject.PROJCTEND = $event"
|
||||||
/>
|
/>
|
||||||
|
<input ref="endDateInput" type="date" v-model="selectedProject.PROJCTEND" class="hidden-end-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
title="설명"
|
title="설명"
|
||||||
@ -199,6 +207,31 @@ const toastStore = useToastStore();
|
|||||||
const userStore = useUserInfoStore();
|
const userStore = useUserInfoStore();
|
||||||
const projectStore = useProjectStore();
|
const projectStore = useProjectStore();
|
||||||
|
|
||||||
|
const startDateInput = ref(null);
|
||||||
|
const endDateInput = ref(null);
|
||||||
|
|
||||||
|
const focusStartDateInput = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (startDateInput.value) {
|
||||||
|
startDateInput.value.focus();
|
||||||
|
setTimeout(() => {
|
||||||
|
startDateInput.value.showPicker?.();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const focusEndDateInput = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (endDateInput.value) {
|
||||||
|
endDateInput.value.focus();
|
||||||
|
setTimeout(() => {
|
||||||
|
endDateInput.value.showPicker?.();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Props 정의
|
// Props 정의
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
@ -548,3 +581,13 @@ onMounted(async () => {
|
|||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.hidden-date-input {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -69,23 +69,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<div class="date-picker-wrapper" @click="focusStartDateInput">
|
||||||
title="시작 일"
|
<FormInput
|
||||||
name="startDay"
|
title="시작 일"
|
||||||
:type="'date'"
|
name="startDay"
|
||||||
:is-essential="true"
|
:type="'date'"
|
||||||
:modelValue="startDay"
|
:is-essential="true"
|
||||||
v-model="startDay"
|
:modelValue="startDay"
|
||||||
/>
|
v-model="startDay"
|
||||||
|
/>
|
||||||
|
<input ref="startDateInput" type="date" v-model="startDay" class="hidden-start-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<div class="date-picker-wrapper" @click="focusEndDateInput">
|
||||||
title="종료 일"
|
<FormInput
|
||||||
:type="'date'"
|
title="종료 일"
|
||||||
name="endDay"
|
name="endDay"
|
||||||
:modelValue="endDay"
|
:type="'date'"
|
||||||
:min = "startDay"
|
:modelValue="endDay"
|
||||||
@update:modelValue="endDay = $event"
|
:min="startDay"
|
||||||
/>
|
@update:modelValue="endDay = $event"
|
||||||
|
/>
|
||||||
|
<input ref="endDateInput" type="date" v-model="endDay" class="hidden-end-input">
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
title="설명"
|
title="설명"
|
||||||
@ -161,6 +167,31 @@
|
|||||||
const nameAlert = ref(false);
|
const nameAlert = ref(false);
|
||||||
const addressAlert = ref(false);
|
const addressAlert = ref(false);
|
||||||
|
|
||||||
|
const startDateInput = ref(null);
|
||||||
|
const endDateInput = ref(null);
|
||||||
|
|
||||||
|
const focusStartDateInput = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (startDateInput.value) {
|
||||||
|
startDateInput.value.focus();
|
||||||
|
setTimeout(() => {
|
||||||
|
startDateInput.value.showPicker?.();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const focusEndDateInput = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
if (endDateInput.value) {
|
||||||
|
endDateInput.value.focus();
|
||||||
|
setTimeout(() => {
|
||||||
|
endDateInput.value.showPicker?.();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const addressData = ref({
|
const addressData = ref({
|
||||||
postcode: '',
|
postcode: '',
|
||||||
address: '',
|
address: '',
|
||||||
|
|||||||
@ -28,7 +28,6 @@
|
|||||||
</button>
|
</button>
|
||||||
<DeleteBtn v-if="!data.localVote.LOCVOTDDT" @click="voteDelete(data.localVote.LOCVOTSEQ)" />
|
<DeleteBtn v-if="!data.localVote.LOCVOTDDT" @click="voteDelete(data.localVote.LOCVOTSEQ)" />
|
||||||
</div>
|
</div>
|
||||||
<p v-if="data.localVote.LOCVOTDDT" class="btn-icon btn-danger rounded-2 pe-none"><i class="bx bx-power-off"></i></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -53,7 +52,7 @@
|
|||||||
<small v-if="yesVotetotal != 0 && !data.localVote.LOCVOTDDT">투표 완료 : 종료시 투표 결과가 나타납니다.</small>
|
<small v-if="yesVotetotal != 0 && !data.localVote.LOCVOTDDT">투표 완료 : 종료시 투표 결과가 나타납니다.</small>
|
||||||
<!-- 투표 결과 -->
|
<!-- 투표 결과 -->
|
||||||
<div v-if="data.localVote.LOCVOTDDT" class="mt-3">
|
<div v-if="data.localVote.LOCVOTDDT" class="mt-3">
|
||||||
<vote-result-list :data="topVoters" @randomList="randomList" :randomResultNum="data.localVote.LOCVOTRES" :locvotreg="data.localVote.LOCVOTREG"/>
|
<vote-result-list :data="topVoters" @randomList="randomList" :randomResultNum="data.localVote.LOCVOTRES" :locvotreg="data.localVote.LOCVOTREG" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 투표완/미완 인원 -->
|
<!-- 투표완/미완 인원 -->
|
||||||
<vote-user-list
|
<vote-user-list
|
||||||
@ -68,7 +67,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref, watch } from 'vue'
|
||||||
import EditBtn from '@c/button/EditBtn.vue';
|
import EditBtn from '@c/button/EditBtn.vue';
|
||||||
import DeleteBtn from '@c/button/DeleteBtn.vue';
|
import DeleteBtn from '@c/button/DeleteBtn.vue';
|
||||||
import voteUserList from '@c/voteboard/voteUserList.vue';
|
import voteUserList from '@c/voteboard/voteUserList.vue';
|
||||||
@ -105,9 +104,10 @@ const topVoters = computed(() => {
|
|||||||
|
|
||||||
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
||||||
const userStore = useUserInfoStore();
|
const userStore = useUserInfoStore();
|
||||||
const currentDate = new Date();
|
const offset = new Date().getTimezoneOffset() * 60000
|
||||||
const voteEndDate = new Date(props.data.localVote.formatted_LOCVOTEDT.replace(' ', 'T'));
|
const today = new Date(Date.now() - offset);
|
||||||
voteEndDate.setDate(voteEndDate.getDate() + 1);
|
const currentDate = today.toISOString().substring(0,16);
|
||||||
|
const voteEndDate = props.data.localVote.LOCVOTEDT.substring(0,16);
|
||||||
// 종료 여부 계산
|
// 종료 여부 계산
|
||||||
const isVoteEnded = computed(() => {
|
const isVoteEnded = computed(() => {
|
||||||
return currentDate > voteEndDate;
|
return currentDate > voteEndDate;
|
||||||
@ -115,9 +115,21 @@ const isVoteEnded = computed(() => {
|
|||||||
const emit = defineEmits(['addContents','checkedNames','endVoteId','voteEnded','randomList','voteDelete','updateVote']);
|
const emit = defineEmits(['addContents','checkedNames','endVoteId','voteEnded','randomList','voteDelete','updateVote']);
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (isVoteEnded.value && !props.data.localVote.LOCVOTDDT) {
|
if (isVoteEnded.value && !props.data.localVote.LOCVOTDDT) {
|
||||||
emit('voteEnded', { id: props.data.localVote.LOCVOTSEQ });
|
emit('voteEnded', { id: props.data.localVote.LOCVOTSEQ });
|
||||||
}
|
}
|
||||||
|
checkVoteCompletion();
|
||||||
});
|
});
|
||||||
|
// 데이터 변경 감지
|
||||||
|
watch(() => props.data.localVote.total_voted, () => {
|
||||||
|
checkVoteCompletion();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 종료 체크 함수
|
||||||
|
const checkVoteCompletion = () => {
|
||||||
|
if (props.data.localVote.total_votable === props.data.localVote.total_voted && props.data.localVote.LOCVOTDDT == '') {
|
||||||
|
emit('voteEnded', { id: props.data.localVote.LOCVOTSEQ });
|
||||||
|
}
|
||||||
|
};
|
||||||
const addContents = (itemList, voteId) =>{
|
const addContents = (itemList, voteId) =>{
|
||||||
emit('addContents',itemList,voteId)
|
emit('addContents',itemList,voteId)
|
||||||
}
|
}
|
||||||
@ -125,7 +137,6 @@ const checkedNames = (numList) =>{
|
|||||||
emit('checkedNames',numList);
|
emit('checkedNames',numList);
|
||||||
}
|
}
|
||||||
const endBtn = (voteid) =>{
|
const endBtn = (voteid) =>{
|
||||||
voteEndDate.setTime(currentDate.getTime()); // 현재 날짜로 설정
|
|
||||||
emit('endVoteId',voteid);
|
emit('endVoteId',voteid);
|
||||||
}
|
}
|
||||||
const voteDelete = (voteid) =>{
|
const voteDelete = (voteid) =>{
|
||||||
|
|||||||
@ -17,16 +17,23 @@
|
|||||||
:is-alert="contentAlerts[index]"
|
:is-alert="contentAlerts[index]"
|
||||||
v-model="item.content"
|
v-model="item.content"
|
||||||
:is-btn="true"
|
:is-btn="true"
|
||||||
|
@keyup="ValidHandler('content' + (index + 1))"
|
||||||
>
|
>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<delete-btn @click="removeItem(index)" />
|
<delete-btn @click="removeItem(index)" />
|
||||||
</template>
|
</template>
|
||||||
</form-input>
|
</form-input>
|
||||||
<link-input v-model="item.url" class="mb-1"/>
|
<form-input
|
||||||
|
:title="'URL ' + (index + data.length + 1)"
|
||||||
|
:name="'url' + index"
|
||||||
|
v-model="item.url"
|
||||||
|
:is-essential="false"
|
||||||
|
class="mb-1"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content align-items-center mt-3">
|
<div class="d-flex justify-content align-items-center mt-3">
|
||||||
<plus-btn @click="addItem" :disabled="total >= 10" />
|
<plus-btn @click="addItem" :disabled=" total >= 10" />
|
||||||
<button class="btn btn-primary btn-icon m-1" @click="addContentSave(item.LOCVOTSEQ)" :disabled="isSaveDisabled">
|
<button class="btn btn-primary btn-icon m-1" @click="addContentSave(item.LOCVOTSEQ ,index)" :disabled="isSaveDisabled">
|
||||||
<i class="bx bx-check"></i>
|
<i class="bx bx-check"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -46,20 +53,19 @@ import SaveBtn from '@c/button/SaveBtn.vue'
|
|||||||
import FormInput from '@c/input/FormInput.vue';
|
import FormInput from '@c/input/FormInput.vue';
|
||||||
import voteCardCheckList from '@c/voteboard/voteCardCheckList.vue';
|
import voteCardCheckList from '@c/voteboard/voteCardCheckList.vue';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import LinkInput from "@/components/voteboard/voteLinkInput.vue";
|
|
||||||
import { voteCommon } from '@s/voteCommon';
|
import { voteCommon } from '@s/voteCommon';
|
||||||
import DeleteBtn from "@c/button/DeleteBtn.vue";
|
import DeleteBtn from "@c/button/DeleteBtn.vue";
|
||||||
import { useToastStore } from '@s/toastStore';
|
import { useToastStore } from '@s/toastStore';
|
||||||
import router from '@/router';
|
import router from '@/router';
|
||||||
const toastStore = useToastStore();
|
const toastStore = useToastStore();
|
||||||
const contentAlerts = ref(false);
|
const contentAlerts = ref([false, false]);
|
||||||
const titleAlert = ref(false);
|
const titleAlert = ref(false);
|
||||||
const title = ref('');
|
const title = ref('');
|
||||||
const rink = ref('');
|
const rink = ref('');
|
||||||
const { itemList, addItem, removeItem } = voteCommon(true);
|
const { itemList, addItem, removeItem } = voteCommon(true);
|
||||||
const total = computed(() => props.total + itemList.value.length);
|
const total = computed(() => props.total + itemList.value.length);
|
||||||
const isSaveDisabled = computed(() => {
|
const isSaveDisabled = computed(() => {
|
||||||
return itemList.value.length === 0 || itemList.value.every(item => !item.content.trim());
|
return itemList.value.length === 0 || itemList.value.every(item => !item.content.trim() && !item.url.trim());
|
||||||
});
|
});
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
@ -77,12 +83,35 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
const emit = defineEmits(['addContents','checkedNames']);
|
const emit = defineEmits(['addContents','checkedNames']);
|
||||||
//항목추가
|
//항목추가
|
||||||
const addContentSave = (voteId) =>{
|
const addContentSave = (voteId,index) =>{
|
||||||
|
let valid = true;
|
||||||
const filteredItemList = itemList.value.filter(item => item.content && item.content.trim() !== '');
|
const filteredItemList = itemList.value.filter(item => item.content && item.content.trim() !== '');
|
||||||
emit('addContents',filteredItemList,voteId);
|
|
||||||
itemList.value = [{ content: "", url: "" }];
|
itemList.value.forEach((item, index) => {
|
||||||
|
if (!item.content.trim() && item.url.trim()) {
|
||||||
|
contentAlerts.value[index] = true;
|
||||||
|
valid = false;
|
||||||
|
} else {
|
||||||
|
contentAlerts.value[index] = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(valid){
|
||||||
|
emit('addContents',filteredItemList,voteId);
|
||||||
|
itemList.value = [{ content: "", url: "" }];
|
||||||
|
removeItem();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ValidHandler = (field) => {
|
||||||
|
if (field.startsWith('content')) {
|
||||||
|
const index = parseInt(field.replace('content', '')) - 1;
|
||||||
|
if (!isNaN(index)) {
|
||||||
|
contentAlerts.value[index] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const checkedNames = ref([]); // 선택된 값 저장
|
const checkedNames = ref([]); // 선택된 값 저장
|
||||||
const updateCheckedNames = (newValues) => {
|
const updateCheckedNames = (newValues) => {
|
||||||
checkedNames.value = newValues;
|
checkedNames.value = newValues;
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div class="timeline-event ps-1">
|
<div class="timeline-event ps-1">
|
||||||
<div class="timeline-header">
|
<div class="timeline-header">
|
||||||
<small class="text-primary text-uppercase">투표결과</small>
|
<small class="text-primary text-uppercase">투표결과</small>
|
||||||
</div>
|
</div>
|
||||||
<h6 v-if="data" class="my-50">{{ data[0].LOCVOTCON }}</h6>
|
<h6 v-if="data" class="my-50">{{ data[0].LOCVOTCON }}</h6>
|
||||||
<h6 v-if="randomResultNum" class="my-50">{{randomResultNum }}</h6>
|
<h6 v-if="randomResultNum" class="my-50">{{randomResultNum }}</h6>
|
||||||
|
|||||||
@ -57,6 +57,7 @@
|
|||||||
v-if="contentLoaded"
|
v-if="contentLoaded"
|
||||||
@update:data="content = $event"
|
@update:data="content = $event"
|
||||||
@update:imageUrls="imageUrls = $event"
|
@update:imageUrls="imageUrls = $event"
|
||||||
|
@update:uploadedImgList="handleUpdateEditorImg"
|
||||||
:initialData="content"
|
:initialData="content"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -115,7 +116,7 @@
|
|||||||
const attachFilesAlert = ref(false);
|
const attachFilesAlert = ref(false);
|
||||||
const isFileValid = ref(true);
|
const isFileValid = ref(true);
|
||||||
const delFileIdx = ref([]); // 제외할 기존 첨부파일 ID
|
const delFileIdx = ref([]); // 제외할 기존 첨부파일 ID
|
||||||
const additionalFiles = ref([]); // 새로 추가할 첨부파일
|
const editorUploadedImgList = ref([]);
|
||||||
|
|
||||||
// 게시물 데이터 로드
|
// 게시물 데이터 로드
|
||||||
const fetchBoardDetails = async () => {
|
const fetchBoardDetails = async () => {
|
||||||
@ -145,6 +146,10 @@
|
|||||||
contentLoaded.value = true;
|
contentLoaded.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleUpdateEditorImg = item => {
|
||||||
|
editorUploadedImgList.value = item;
|
||||||
|
};
|
||||||
|
|
||||||
// 기존 첨부파일명을 노출
|
// 기존 첨부파일명을 노출
|
||||||
const addDisplayFileName = fileInfos =>
|
const addDisplayFileName = fileInfos =>
|
||||||
fileInfos.map(file => ({
|
fileInfos.map(file => ({
|
||||||
@ -247,6 +252,11 @@
|
|||||||
boardData.delFileIdx = [...delFileIdx.value];
|
boardData.delFileIdx = [...delFileIdx.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 에디터에 업로드 된 이미지 인덱스 목록
|
||||||
|
if (editorUploadedImgList.value && editorUploadedImgList.value.length > 0) {
|
||||||
|
boardData.editorUploadedImgList = [...editorUploadedImgList.value];
|
||||||
|
}
|
||||||
|
|
||||||
const fileArray = newFileFilter(attachFiles);
|
const fileArray = newFileFilter(attachFiles);
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
|
|||||||
@ -101,7 +101,7 @@
|
|||||||
<span v-if="isNewPost(post.rawDate)" class="box-new badge text-white ms-2 fs-tiny">N</span>
|
<span v-if="isNewPost(post.rawDate)" class="box-new badge text-white ms-2 fs-tiny">N</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">{{ post.author }}</td>
|
<td class="text-center">{{ post.nickname ? post.nickname : post.author }}</td>
|
||||||
<td class="text-center">{{ post.date }}</td>
|
<td class="text-center">{{ post.date }}</td>
|
||||||
<td class="text-center">{{ post.views }}</td>
|
<td class="text-center">{{ post.views }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -219,6 +219,7 @@
|
|||||||
date: formatDate(post.date), // 날짜 변환 적용
|
date: formatDate(post.date), // 날짜 변환 적용
|
||||||
views: post.cnt || 0,
|
views: post.cnt || 0,
|
||||||
hasAttachment: post.hasAttachment,
|
hasAttachment: post.hasAttachment,
|
||||||
|
nickname: post.nickname || null,
|
||||||
img: post.firstImageUrl || null,
|
img: post.firstImageUrl || null,
|
||||||
commentCount: post.commentCount,
|
commentCount: post.commentCount,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -8,10 +8,11 @@
|
|||||||
<div class="pb-5 border-bottom">
|
<div class="pb-5 border-bottom">
|
||||||
<BoardProfile
|
<BoardProfile
|
||||||
:boardId="currentBoardId"
|
:boardId="currentBoardId"
|
||||||
:profileName="profileName"
|
:profileName="displayName"
|
||||||
:unknown="unknown"
|
:unknown="unknown"
|
||||||
:profileImg="profileImg"
|
:profileImg="profileImg"
|
||||||
:views="views"
|
:views="views"
|
||||||
|
:nickname="nickname"
|
||||||
:commentNum="commentNum"
|
:commentNum="commentNum"
|
||||||
:date="formattedBoardDate"
|
:date="formattedBoardDate"
|
||||||
:isLike="false"
|
:isLike="false"
|
||||||
@ -151,6 +152,7 @@
|
|||||||
const profileName = ref('');
|
const profileName = ref('');
|
||||||
const boardTitle = ref('제목 없음');
|
const boardTitle = ref('제목 없음');
|
||||||
const boardContent = ref('');
|
const boardContent = ref('');
|
||||||
|
const nickname = ref('');
|
||||||
const date = ref('');
|
const date = ref('');
|
||||||
const views = ref(0);
|
const views = ref(0);
|
||||||
const likes = ref(0);
|
const likes = ref(0);
|
||||||
@ -174,6 +176,10 @@
|
|||||||
const authorId = ref(''); // 작성자 id
|
const authorId = ref(''); // 작성자 id
|
||||||
const editCommentAlert = ref({}); //댓글, 대댓글 오류 메세지 객체
|
const editCommentAlert = ref({}); //댓글, 대댓글 오류 메세지 객체
|
||||||
|
|
||||||
|
const displayName = computed(() => {
|
||||||
|
return nickname.value && unknown.value ? nickname.value : profileName.value;
|
||||||
|
});
|
||||||
|
|
||||||
const isAuthor = computed(() => currentUserId.value === authorId.value);
|
const isAuthor = computed(() => currentUserId.value === authorId.value);
|
||||||
const commentsWithAuthStatus = computed(() => {
|
const commentsWithAuthStatus = computed(() => {
|
||||||
const updatedComments = comments.value.map(comment => ({
|
const updatedComments = comments.value.map(comment => ({
|
||||||
@ -257,6 +263,7 @@
|
|||||||
boardContent.value = boardData.content || '';
|
boardContent.value = boardData.content || '';
|
||||||
profileImg.value = boardData.profileImg || '';
|
profileImg.value = boardData.profileImg || '';
|
||||||
date.value = boardData.date || '';
|
date.value = boardData.date || '';
|
||||||
|
nickname.value = boardData.nickname || '';
|
||||||
views.value = boardData.cnt || 0;
|
views.value = boardData.cnt || 0;
|
||||||
likes.value = boardData.likeCount || 0;
|
likes.value = boardData.likeCount || 0;
|
||||||
dislikes.value = boardData.dislikeCount || 0;
|
dislikes.value = boardData.dislikeCount || 0;
|
||||||
@ -322,7 +329,7 @@
|
|||||||
likeCount: comment.likeCount || 0,
|
likeCount: comment.likeCount || 0,
|
||||||
dislikeCount: comment.dislikeCount || 0,
|
dislikeCount: comment.dislikeCount || 0,
|
||||||
profileImg: comment.profileImg || '',
|
profileImg: comment.profileImg || '',
|
||||||
nickname: comment.LOCCMTNIC,
|
nickname: comment.LOCCMTNIC || '',
|
||||||
likeClicked: comment.likeClicked || false,
|
likeClicked: comment.likeClicked || false,
|
||||||
dislikeClicked: comment.dislikeClicked || false,
|
dislikeClicked: comment.dislikeClicked || false,
|
||||||
createdAtRaw: comment.LOCCMTRDT, // 작성일
|
createdAtRaw: comment.LOCCMTRDT, // 작성일
|
||||||
@ -352,7 +359,7 @@
|
|||||||
parentId: reply.LOCCMTPNT, // 부모 댓글 ID
|
parentId: reply.LOCCMTPNT, // 부모 댓글 ID
|
||||||
content: reply.LOCCMTRPY || '내용 없음',
|
content: reply.LOCCMTRPY || '내용 없음',
|
||||||
createdAtRaw: reply.LOCCMTRDT,
|
createdAtRaw: reply.LOCCMTRDT,
|
||||||
nickname: reply.LOCCMTNIC,
|
nickname: reply.LOCCMTNIC || '',
|
||||||
// createdAt: formattedDate(reply.LOCCMTRDT),
|
// createdAt: formattedDate(reply.LOCCMTRDT),
|
||||||
//createdAtRaw: new Date(reply.LOCCMTUDT),
|
//createdAtRaw: new Date(reply.LOCCMTUDT),
|
||||||
createdAt: formattedDate(reply.LOCCMTUDT) + (reply.LOCCMTUDT !== reply.LOCCMTRDT ? ' (수정됨)' : ''),
|
createdAt: formattedDate(reply.LOCCMTUDT) + (reply.LOCCMTUDT !== reply.LOCCMTRDT ? ' (수정됨)' : ''),
|
||||||
@ -435,7 +442,7 @@
|
|||||||
LOCCMTRPY: reply.comment,
|
LOCCMTRPY: reply.comment,
|
||||||
LOCCMTPWD: reply.password || null,
|
LOCCMTPWD: reply.password || null,
|
||||||
LOCCMTPNT: reply.parentId,
|
LOCCMTPNT: reply.parentId,
|
||||||
LOCCMTNIC: data.isCheck ? data.nickname : null,
|
LOCCMTNIC: reply.isCheck ? reply.nickname : null,
|
||||||
LOCBRDTYP: reply.isCheck ? '300102' : null,
|
LOCBRDTYP: reply.isCheck ? '300102' : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -42,6 +42,15 @@
|
|||||||
|
|
||||||
<!-- 비밀번호 필드 (익명게시판 선택 시 활성화) -->
|
<!-- 비밀번호 필드 (익명게시판 선택 시 활성화) -->
|
||||||
<div v-if="categoryValue === 300102" class="mb-4">
|
<div v-if="categoryValue === 300102" class="mb-4">
|
||||||
|
<FormInput
|
||||||
|
title="닉네임"
|
||||||
|
name="nickname"
|
||||||
|
:is-essential="true"
|
||||||
|
:is-alert="nicknameAlert"
|
||||||
|
v-model="nickname"
|
||||||
|
@update:alert="nicknameAlert = $event"
|
||||||
|
@input="validateNickname"
|
||||||
|
/>
|
||||||
<FormInput
|
<FormInput
|
||||||
title="비밀번호"
|
title="비밀번호"
|
||||||
name="pw"
|
name="pw"
|
||||||
@ -83,7 +92,7 @@
|
|||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label class="col-md-2 col-form-label"> 내용 <span class="text-danger">*</span> </label>
|
<label class="col-md-2 col-form-label"> 내용 <span class="text-danger">*</span> </label>
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<QEditor @update:data="content = $event" />
|
<QEditor @update:data="content = $event" @update:uploadedImgList="handleUpdateEditorImg" />
|
||||||
</div>
|
</div>
|
||||||
<div class="invalid-feedback mt-1" :class="contentAlert ? 'd-block' : 'd-none'">내용을 입력해주세요.</div>
|
<div class="invalid-feedback mt-1" :class="contentAlert ? 'd-block' : 'd-none'">내용을 입력해주세요.</div>
|
||||||
</div>
|
</div>
|
||||||
@ -112,12 +121,14 @@
|
|||||||
const toastStore = useToastStore();
|
const toastStore = useToastStore();
|
||||||
const categoryList = ref([]);
|
const categoryList = ref([]);
|
||||||
const title = ref('');
|
const title = ref('');
|
||||||
|
const nickname = ref("");
|
||||||
const password = ref('');
|
const password = ref('');
|
||||||
const categoryValue = ref(null);
|
const categoryValue = ref(null);
|
||||||
const content = ref({ ops: [] });
|
const content = ref({ ops: [] });
|
||||||
const isFileValid = ref(true);
|
const isFileValid = ref(true);
|
||||||
|
|
||||||
const titleAlert = ref(false);
|
const titleAlert = ref(false);
|
||||||
|
const nicknameAlert = ref(false);
|
||||||
const passwordAlert = ref(false);
|
const passwordAlert = ref(false);
|
||||||
const contentAlert = ref(false);
|
const contentAlert = ref(false);
|
||||||
const categoryAlert = ref(false);
|
const categoryAlert = ref(false);
|
||||||
@ -127,6 +138,7 @@
|
|||||||
const maxFiles = 5;
|
const maxFiles = 5;
|
||||||
const maxSize = 10 * 1024 * 1024;
|
const maxSize = 10 * 1024 * 1024;
|
||||||
const fileError = ref('');
|
const fileError = ref('');
|
||||||
|
const editorUploadedImgList = ref([]);
|
||||||
|
|
||||||
const fetchCategories = async () => {
|
const fetchCategories = async () => {
|
||||||
const response = await axios.get('board/categories');
|
const response = await axios.get('board/categories');
|
||||||
@ -143,6 +155,10 @@
|
|||||||
|
|
||||||
const fileCount = computed(() => attachFiles.value.length);
|
const fileCount = computed(() => attachFiles.value.length);
|
||||||
|
|
||||||
|
const handleUpdateEditorImg = item => {
|
||||||
|
editorUploadedImgList.value = item;
|
||||||
|
};
|
||||||
|
|
||||||
const handleFileUpload = files => {
|
const handleFileUpload = files => {
|
||||||
const validFiles = files.filter(file => file.size <= maxSize);
|
const validFiles = files.filter(file => file.size <= maxSize);
|
||||||
if (files.some(file => file.size > maxSize)) {
|
if (files.some(file => file.size > maxSize)) {
|
||||||
@ -172,6 +188,14 @@
|
|||||||
titleAlert.value = title.value.trim().length === 0;
|
titleAlert.value = title.value.trim().length === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validateNickname = () => {
|
||||||
|
if (categoryValue.value === 300102) {
|
||||||
|
nicknameAlert.value = nickname.value.trim().length === 0;
|
||||||
|
} else {
|
||||||
|
nicknameAlert.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const validatePassword = () => {
|
const validatePassword = () => {
|
||||||
if (categoryValue.value === 300102) {
|
if (categoryValue.value === 300102) {
|
||||||
password.value = password.value.replace(/\s/g, ''); // 공백 제거
|
password.value = password.value.replace(/\s/g, ''); // 공백 제거
|
||||||
@ -199,11 +223,12 @@
|
|||||||
/** 글쓰기 */
|
/** 글쓰기 */
|
||||||
const write = async () => {
|
const write = async () => {
|
||||||
validateTitle();
|
validateTitle();
|
||||||
|
validateNickname();
|
||||||
validatePassword();
|
validatePassword();
|
||||||
validateContent();
|
validateContent();
|
||||||
categoryAlert.value = categoryValue.value == null;
|
categoryAlert.value = categoryValue.value == null;
|
||||||
|
|
||||||
if (titleAlert.value || passwordAlert.value || contentAlert.value || categoryAlert.value || !isFileValid.value) {
|
if (titleAlert.value || nicknameAlert.value || passwordAlert.value || contentAlert.value || categoryAlert.value || !isFileValid.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +236,16 @@
|
|||||||
const boardData = {
|
const boardData = {
|
||||||
LOCBRDTTL: title.value,
|
LOCBRDTTL: title.value,
|
||||||
LOCBRDCON: JSON.stringify(content.value), // Delta 포맷을 JSON으로 변환
|
LOCBRDCON: JSON.stringify(content.value), // Delta 포맷을 JSON으로 변환
|
||||||
|
LOCBRDNIC: categoryValue.value === 300102 ? nickname.value : null,
|
||||||
LOCBRDPWD: categoryValue.value === 300102 ? password.value : null,
|
LOCBRDPWD: categoryValue.value === 300102 ? password.value : null,
|
||||||
LOCBRDTYP: categoryValue.value,
|
LOCBRDTYP: categoryValue.value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 에디터에 업로드 된 이미지 인덱스 목록
|
||||||
|
if (editorUploadedImgList.value && editorUploadedImgList.value.length > 0) {
|
||||||
|
boardData.editorUploadedImgList = [...editorUploadedImgList.value];
|
||||||
|
}
|
||||||
|
|
||||||
const { data: boardResponse } = await axios.post('board', boardData);
|
const { data: boardResponse } = await axios.post('board', boardData);
|
||||||
const boardId = boardResponse.data;
|
const boardId = boardResponse.data;
|
||||||
// 첨부파일 업로드 (비동기 병렬 처리)
|
// 첨부파일 업로드 (비동기 병렬 처리)
|
||||||
|
|||||||
@ -180,7 +180,6 @@ function handleDateClick(info) {
|
|||||||
|
|
||||||
// 이미 활성화된 날짜를 한 번 더 클릭하면 비활성화
|
// 이미 활성화된 날짜를 한 번 더 클릭하면 비활성화
|
||||||
if (currentValue && currentValue !== "delete") {
|
if (currentValue && currentValue !== "delete") {
|
||||||
console.log("🛑 활성화된 날짜 비활성화:", clickedDateStr);
|
|
||||||
selectedDates.value.delete(clickedDateStr);
|
selectedDates.value.delete(clickedDateStr);
|
||||||
updateCalendarEvents();
|
updateCalendarEvents();
|
||||||
return;
|
return;
|
||||||
@ -203,7 +202,6 @@ function handleDateClick(info) {
|
|||||||
|
|
||||||
// 버튼을 눌렀을 때 - 기존 휴가 삭제 후 새로운 값 추가
|
// 버튼을 눌렀을 때 - 기존 휴가 삭제 후 새로운 값 추가
|
||||||
if (isMyVacation) {
|
if (isMyVacation) {
|
||||||
console.log("🗑 기존 휴가 삭제 후 새로운 상태 추가:", clickedDateStr);
|
|
||||||
selectedDates.value.set(clickedDateStr, "delete");
|
selectedDates.value.set(clickedDateStr, "delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,7 +645,7 @@ onMounted(async () => {
|
|||||||
const dpEl = calendarDatepicker.value;
|
const dpEl = calendarDatepicker.value;
|
||||||
dpEl.style.display = 'block';
|
dpEl.style.display = 'block';
|
||||||
dpEl.style.position = 'fixed';
|
dpEl.style.position = 'fixed';
|
||||||
dpEl.style.top = '25%';
|
dpEl.style.top = '18%';
|
||||||
dpEl.style.left = '50%';
|
dpEl.style.left = '50%';
|
||||||
dpEl.style.transform = 'translate(-50%, -50%)';
|
dpEl.style.transform = 'translate(-50%, -50%)';
|
||||||
dpEl.style.zIndex = '9999';
|
dpEl.style.zIndex = '9999';
|
||||||
|
|||||||
@ -132,17 +132,18 @@ const checkedNames = (numList) => {
|
|||||||
}
|
}
|
||||||
//투표종료
|
//투표종료
|
||||||
const endVoteId = (endVoteId) => {
|
const endVoteId = (endVoteId) => {
|
||||||
|
console.log('endVoteId',endVoteId)
|
||||||
$api.patch('vote/updateEndData',{
|
$api.patch('vote/updateEndData',{
|
||||||
endVoteId :endVoteId
|
endVoteId :endVoteId
|
||||||
}).then((res)=>{
|
}).then((res)=>{
|
||||||
if(res.data.status === 'OK'){
|
if(res.data.status === 'OK'){
|
||||||
toastStore.onToast('투표가 종료되었습니다.', 's');
|
|
||||||
getvoteList();
|
getvoteList();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
//기한 지난 투표 종료
|
//기한 지난 투표 종료
|
||||||
const voteEnded = async (id) =>{
|
const voteEnded = async (id) =>{
|
||||||
|
console.log('voteEnded',id)
|
||||||
await endVoteId(id.id);
|
await endVoteId(id.id);
|
||||||
}
|
}
|
||||||
//투표 삭제
|
//투표 삭제
|
||||||
|
|||||||
@ -20,16 +20,22 @@
|
|||||||
v-model="title"
|
v-model="title"
|
||||||
@keyup="ValidHandler('title')"
|
@keyup="ValidHandler('title')"
|
||||||
/>
|
/>
|
||||||
<form-input
|
<div class="date-picker-container" @click="focusDateInput">
|
||||||
title="종료날짜"
|
<form-input
|
||||||
name="endDate"
|
title="종료날짜"
|
||||||
type="date"
|
name="endDate"
|
||||||
:is-essential="true"
|
type="datetime-local"
|
||||||
:is-alert="endDateAlert"
|
:is-essential="true"
|
||||||
v-model="endDate"
|
:is-alert="endDateAlert"
|
||||||
:min="today"
|
v-model="endDate"
|
||||||
@change="ValidHandlerendDate"
|
:min="minDate"
|
||||||
/>
|
@input="ValidHandlerendDate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 숨겨진 input 태그를 사용하여 강제로 포커스 -->
|
||||||
|
<input ref="dateInput" type="datetime-local" v-model="endDate" class="hidden-date-input">
|
||||||
|
|
||||||
<!-- 항목 입력 반복 -->
|
<!-- 항목 입력 반복 -->
|
||||||
<div v-for="(item, index) in itemList" :key="index">
|
<div v-for="(item, index) in itemList" :key="index">
|
||||||
<form-input
|
<form-input
|
||||||
@ -45,8 +51,14 @@
|
|||||||
<delete-btn @click="removeItem(index)" :disabled="index < 2" />
|
<delete-btn @click="removeItem(index)" :disabled="index < 2" />
|
||||||
</template>
|
</template>
|
||||||
</form-input>
|
</form-input>
|
||||||
|
<form-input
|
||||||
<link-input v-model="item.url" class="mb-1"/>
|
:title="'URL ' + (index + 1)"
|
||||||
|
:name="'url' + index"
|
||||||
|
v-model="item.url"
|
||||||
|
:is-essential="false"
|
||||||
|
class="mb-1"
|
||||||
|
/>
|
||||||
|
<!-- <link-input v-model="item.url" class="mb-1"/> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<plus-btn @click="addItem" :disabled="itemList.length >= 10" class="mb-3" />
|
<plus-btn @click="addItem" :disabled="itemList.length >= 10" class="mb-3" />
|
||||||
@ -90,7 +102,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, toRaw } from "vue";
|
import { nextTick, onMounted, ref, toRaw } from "vue";
|
||||||
import UserList from "@c/user/UserList.vue";
|
import UserList from "@c/user/UserList.vue";
|
||||||
import formInput from "@c/input/FormInput.vue";
|
import formInput from "@c/input/FormInput.vue";
|
||||||
import { useToastStore } from "@s/toastStore";
|
import { useToastStore } from "@s/toastStore";
|
||||||
@ -98,13 +110,15 @@ import PlusBtn from "@c/button/PlusBtn.vue";
|
|||||||
import DeleteBtn from "@c/button/DeleteBtn.vue";
|
import DeleteBtn from "@c/button/DeleteBtn.vue";
|
||||||
import $api from "@api";
|
import $api from "@api";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import LinkInput from "@/components/voteboard/voteLinkInput.vue";
|
|
||||||
import { voteCommon } from '@s/voteCommon';
|
import { voteCommon } from '@s/voteCommon';
|
||||||
import { useUserStore } from '@s/userList';
|
import { useUserStore } from '@s/userList';
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const today = new Date().toISOString().substring(0, 10);
|
// const offset = new Date().getTimezoneOffset() * 60000
|
||||||
|
// const today = new Date(Date.now() - offset);
|
||||||
|
// today.setDate(today.getDate() + 1);
|
||||||
|
// const minDate = today.toISOString().substring(0, 16);
|
||||||
const toastStore = useToastStore();
|
const toastStore = useToastStore();
|
||||||
const activeUserList = ref([]);
|
const activeUserList = ref([]);
|
||||||
const disabledUsers = ref([]);
|
const disabledUsers = ref([]);
|
||||||
@ -119,12 +133,29 @@ const userListTotal = ref(0);
|
|||||||
const addvoteitem = ref(false);
|
const addvoteitem = ref(false);
|
||||||
const addvotemulti= ref(false);
|
const addvotemulti= ref(false);
|
||||||
|
|
||||||
|
const dateInput = ref(null);
|
||||||
|
|
||||||
|
const focusDateInput = () => {
|
||||||
|
if (dateInput.value) {
|
||||||
|
dateInput.value.showPicker(); // 달력 자동 열기 (일부 브라우저에서 지원)
|
||||||
|
dateInput.value.focus(); // 포커스 이동
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const minDate = ref('');
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
const offset = new Date().getTimezoneOffset() * 60000;
|
||||||
|
const today = new Date(Date.now() - offset);
|
||||||
|
today.setDate(today.getDate() + 1);
|
||||||
|
minDate.value = today.toISOString().substring(0, 16);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const userSet = ({ userList, userTotal }) => {
|
const userSet = ({ userList, userTotal }) => {
|
||||||
activeUserList.value = userList;
|
activeUserList.value = userList;
|
||||||
userListTotal.value = userTotal;
|
userListTotal.value = userTotal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleUserListUpdate = ({ activeUsers, disabledUsers: updatedDisabledUsers }) => {
|
const handleUserListUpdate = ({ activeUsers, disabledUsers: updatedDisabledUsers }) => {
|
||||||
activeUserList.value = activeUsers;
|
activeUserList.value = activeUsers;
|
||||||
disabledUsers.value = updatedDisabledUsers;
|
disabledUsers.value = updatedDisabledUsers;
|
||||||
@ -135,7 +166,6 @@ const handleUserListUpdate = ({ activeUsers, disabledUsers: updatedDisabledUsers
|
|||||||
UserListAlert.value = false;
|
UserListAlert.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveValid = () => {
|
const saveValid = () => {
|
||||||
let valid = true;
|
let valid = true;
|
||||||
if (disabledUsers.value.length === 0) {
|
if (disabledUsers.value.length === 0) {
|
||||||
@ -175,7 +205,6 @@ const saveValid = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const saveVote = () => {
|
const saveVote = () => {
|
||||||
console.log('itemList',itemList)
|
|
||||||
const filteredItemList = itemList.value.filter(item => item.content && item.content.trim() !== '');
|
const filteredItemList = itemList.value.filter(item => item.content && item.content.trim() !== '');
|
||||||
const unwrappedUserList = toRaw(activeUserList.value);
|
const unwrappedUserList = toRaw(activeUserList.value);
|
||||||
const listId = unwrappedUserList.map(item => ({
|
const listId = unwrappedUserList.map(item => ({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user