Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-front
This commit is contained in:
commit
f248141108
@ -1,6 +1,2 @@
|
||||
/* 여기에 dark css 작성 */
|
||||
|
||||
|
||||
.display-block {
|
||||
display: block !important;
|
||||
}
|
||||
@ -1,11 +1,6 @@
|
||||
/* 여기에 light css 작성 */
|
||||
|
||||
|
||||
.display-block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
|
||||
/* 휴가 */
|
||||
|
||||
.fc-daygrid-day-events {
|
||||
@ -111,11 +106,7 @@ opacity: 0.6; /* 흐려 보이게 */
|
||||
border-radius: 5px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
/* 모달 본문 스크롤 */
|
||||
.modal-body {
|
||||
max-height: 130px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
||||
/* 선물하기 모달 */
|
||||
|
||||
@ -162,30 +153,6 @@ opacity: 0.6; /* 흐려 보이게 */
|
||||
color: #ff0800; /* 호버 시 아이콘 색상 변경 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 모달 배경 투명하게 */
|
||||
.modal-dialog {
|
||||
background: none !important; /* 배경 제거 */
|
||||
box-shadow: none !important; /* 음영 제거 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 모달 내용 스타일 */
|
||||
.modal-content {
|
||||
background: #fff; /* 기존 흰색 배경 유지 */
|
||||
border-radius: 8px;
|
||||
box-shadow: none !important; /* 내부 음영 제거 */
|
||||
padding: 20px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.grayscaleImg {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
2
public/vendor/css/rtl/core.css
vendored
2
public/vendor/css/rtl/core.css
vendored
File diff suppressed because one or more lines are too long
@ -40,39 +40,39 @@ const common = {
|
||||
return null; // Delta 객체가 아니거나 ops가 없을 경우 null 반환
|
||||
},
|
||||
|
||||
// /**
|
||||
// * Date 타입 문자열 포멧팅
|
||||
// *
|
||||
// * @param {string} dateStr
|
||||
// * @return
|
||||
// * 1. Date type 인 경우 예시 '25-02-24 12:02'
|
||||
// * 2. Date type 이 아닌 경우 입력값 리턴
|
||||
// *
|
||||
// */
|
||||
// dateFormatter(dateStr) {
|
||||
// const date = new Date(dateStr);
|
||||
// const dateCheck = date.getTime();
|
||||
/**
|
||||
* Date 타입 문자열 포멧팅
|
||||
*
|
||||
* @param {string} dateStr
|
||||
* @return
|
||||
* 1. Date type 인 경우 예시 '25-02-24 12:02'
|
||||
* 2. Date type 이 아닌 경우 입력값 리턴
|
||||
*
|
||||
*/
|
||||
dateFormatter(dateStr) {
|
||||
const date = new Date(dateStr);
|
||||
const dateCheck = date.getTime();
|
||||
|
||||
// if (isNaN(dateCheck)) {
|
||||
// return dateStr;
|
||||
// } else {
|
||||
// const { year, month, day, hours, minutes } = this.formatDateTime(date);
|
||||
// return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
// }
|
||||
// },
|
||||
if (isNaN(dateCheck)) {
|
||||
return dateStr;
|
||||
} else {
|
||||
const { year, month, day, hours, minutes } = this.formatDateTime(date);
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
}
|
||||
},
|
||||
|
||||
// formatDateTime(date) {
|
||||
// const zeroFormat = num => (num < 10 ? `0${num}` : num);
|
||||
formatDateTime(date) {
|
||||
const zeroFormat = num => (num < 10 ? `0${num}` : num);
|
||||
|
||||
// return {
|
||||
// year: date.getFullYear(),
|
||||
// month: zeroFormat(date.getMonth() + 1),
|
||||
// day: zeroFormat(date.getDate()),
|
||||
// hours: zeroFormat(date.getHours()),
|
||||
// minutes: zeroFormat(date.getMinutes()),
|
||||
// seconds: zeroFormat(date.getSeconds()),
|
||||
// };
|
||||
// },
|
||||
return {
|
||||
year: date.getFullYear(),
|
||||
month: zeroFormat(date.getMonth() + 1),
|
||||
day: zeroFormat(date.getDate()),
|
||||
hours: zeroFormat(date.getHours()),
|
||||
minutes: zeroFormat(date.getMinutes()),
|
||||
seconds: zeroFormat(date.getSeconds()),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="mb-2 row" >
|
||||
<div class="mb-2 row">
|
||||
<div class="d-flex">
|
||||
<label :for="name" class="col-md-2 col-form-label">
|
||||
{{ title }}
|
||||
@ -28,7 +28,6 @@
|
||||
placeholder="기본주소"
|
||||
readonly
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -87,7 +86,11 @@ const props = defineProps({
|
||||
},
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
default: () => ({
|
||||
postcode: '',
|
||||
address: '',
|
||||
detailAddress: ''
|
||||
}),
|
||||
required: false
|
||||
}
|
||||
});
|
||||
@ -95,13 +98,13 @@ const props = defineProps({
|
||||
// watch 설정 수정
|
||||
watch(() => props.modelValue, (newValue) => {
|
||||
if (newValue) {
|
||||
postcode.value = newValue.PROJCTZIP || '';
|
||||
address.value = newValue.PROJCTARR || '';
|
||||
detailAddress.value = newValue.PROJCTDTL || '';
|
||||
postcode.value = newValue.postcode || '';
|
||||
address.value = newValue.address || '';
|
||||
detailAddress.value = newValue.detailAddress || '';
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
const emits = defineEmits(['update:data', 'update:alert']);
|
||||
const emits = defineEmits(['update:data', 'update:alert', 'update:modelValue']);
|
||||
|
||||
// 주소 검색 팝업 열기
|
||||
const openAddressSearch = () => {
|
||||
@ -136,6 +139,7 @@ const emitAddressData = () => {
|
||||
detailAddress: detailAddress.value,
|
||||
};
|
||||
emits('update:data', fullAddress);
|
||||
emits('update:modelValue', fullAddress); // modelValue도 부모로 전달
|
||||
};
|
||||
|
||||
// isAlert를 false로 설정
|
||||
|
||||
@ -16,12 +16,12 @@
|
||||
:min="min"
|
||||
@focusout="$emit('focusout', modelValue)"
|
||||
/>
|
||||
<div class="invalid-feedback" :class="isAlert ? 'display-block' : ''">
|
||||
<div class="invalid-feedback" :class="isAlert ? 'd-block' : ''">
|
||||
{{ title }}을 확인해주세요.
|
||||
</div>
|
||||
<!-- 카테고리 중복 -->
|
||||
<div class="invalid-feedback" :class="isCateAlert ? 'display-block' : ''">
|
||||
카테고리는 중복이거나 공백이면 안됩니다. 확인해주세요.
|
||||
<div class="invalid-feedback" :class="isCateAlert ? 'd-block' : ''">
|
||||
카테고리 중복입니다.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -83,7 +83,8 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
// Emits 정의
|
||||
const emits = defineEmits(['update:modelValue', 'focusout']);
|
||||
const emits = defineEmits(['update:modelValue', 'focusout', 'update:alert']);
|
||||
|
||||
|
||||
// 로컬 상태로 사용하기 위한 `inputValue`
|
||||
const inputValue = ref(props.modelValue);
|
||||
@ -91,6 +92,11 @@ const inputValue = ref(props.modelValue);
|
||||
// 부모로 데이터 업데이트
|
||||
watch(inputValue, (newValue) => {
|
||||
emits('update:modelValue', newValue);
|
||||
|
||||
// 값이 입력될 때 `alert`를 false로 설정
|
||||
if (newValue.trim() !== '') {
|
||||
emits('update:alert', false);
|
||||
}
|
||||
});
|
||||
|
||||
// 초기값 동기화
|
||||
@ -99,10 +105,7 @@ watch(() => props.modelValue, (newValue) => {
|
||||
inputValue.value = newValue;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.none {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -3,8 +3,13 @@
|
||||
<div class="row g-0">
|
||||
<div class="card-body">
|
||||
<!-- 제목 -->
|
||||
<h5 class="card-title">
|
||||
<h5 class="card-title d-flex justify-content-between">
|
||||
{{ title }}
|
||||
|
||||
<div>
|
||||
<EditBtn @click.stop="openEditModal" />
|
||||
<DeleteBtn @click.stop="handleDelete" class="ms-1"/>
|
||||
</div>
|
||||
</h5>
|
||||
<!-- 날짜 -->
|
||||
<div class="d-flex flex-column flex-sm-row align-items-center pb-2">
|
||||
@ -27,20 +32,13 @@
|
||||
<!-- 주소 -->
|
||||
<div class="d-flex flex-column flex-sm-row align-items-center pb-2">
|
||||
<div class="d-flex" @click.stop="isPopoverVisible = !isPopoverVisible">
|
||||
<i
|
||||
class="bx bxs-map cursor-pointer"
|
||||
ref="mapIconRef"
|
||||
></i>
|
||||
<i class="bx bxs-map cursor-pointer" ref="mapIconRef"></i>
|
||||
<div class="ms-2">주소</div>
|
||||
</div>
|
||||
<div class="ms-12 position-relative">
|
||||
{{ address }} {{ addressdtail }}
|
||||
<!-- 팝오버 -->
|
||||
<div
|
||||
v-if="isPopoverVisible"
|
||||
class="position-absolute w-100 map text-end"
|
||||
@click.stop
|
||||
>
|
||||
<div v-if="isPopoverVisible" class="position-absolute w-100 map text-end">
|
||||
<button type="button" class="btn-close popover-close" @click.stop="isPopoverVisible = !isPopoverVisible"></button>
|
||||
<div class="card">
|
||||
<div class="card-body p-1">
|
||||
@ -48,6 +46,7 @@
|
||||
v-if="coordinates"
|
||||
:lat="coordinates.lat"
|
||||
:lng="coordinates.lng"
|
||||
:draggable="false"
|
||||
class="w-100 h-px-200"
|
||||
>
|
||||
<KakaoMapMarker
|
||||
@ -59,39 +58,122 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn ms-auto text-white" :style="`background-color: ${projctCol} !important;`" @click.stop="openModal">log</button>
|
||||
<button type="button" class="btn ms-auto text-white" :style="`background-color: ${projctColor} !important;`" @click.stop="openModal">log</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 로그 모달 -->
|
||||
<CenterModal :display="isModalOpen" @close="closeModal">
|
||||
<template #title> Log </template>
|
||||
<template #body>
|
||||
<div class="ms-4 mt-2 border p-3" v-if="logData">
|
||||
<p class="mb-1">{{ logData.createDate }}</p>
|
||||
<strong>[{{ logData.creator }}] 프로젝트 등록</strong>
|
||||
</div>
|
||||
|
||||
<div class="log-item" v-if="logData?.updateDate">
|
||||
<div class="ms-4 mt-2 border p-3">
|
||||
<p class="mb-1">{{ logData.updateDate }}</p>
|
||||
<strong>[{{ logData.updater }}] 프로젝트 수정</strong>
|
||||
<div v-if="logData.length > 0">
|
||||
<div
|
||||
v-for="(log, index) in logData"
|
||||
:key="index"
|
||||
class="ms-4 mt-2 border p-3"
|
||||
>
|
||||
<p class="mb-1">{{ log.logDate }}</p>
|
||||
<strong>{{ log.logMessage }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<template #footer>
|
||||
<button type="button" class="btn btn-secondary" @click="closeModal">닫기</button>
|
||||
<BackBtn @click="closeModal" />
|
||||
</template>
|
||||
</CenterModal>
|
||||
|
||||
<!-- 수정 모달 -->
|
||||
<CenterModal :display="isEditModalOpen" @close="closeEditModal">
|
||||
<template #title> 프로젝트 수정 </template>
|
||||
<template #body>
|
||||
<FormInput
|
||||
title="이름"
|
||||
name="name"
|
||||
:is-essential="true"
|
||||
:is-alert="nameAlert"
|
||||
:modelValue="selectedProject.PROJCTNAM"
|
||||
@update:modelValue="selectedProject.PROJCTNAM = $event"
|
||||
@update:alert="nameAlert = $event"
|
||||
/>
|
||||
|
||||
<FormSelect
|
||||
title="컬러"
|
||||
name="color"
|
||||
:is-essential="true"
|
||||
:is-label="true"
|
||||
:is-common="true"
|
||||
:data="allColors"
|
||||
:value="selectedProject.PROJCTCOL"
|
||||
@update:data="selectedProject.PROJCTCOL = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="시작일"
|
||||
type="date"
|
||||
name="startDay"
|
||||
:is-essential="true"
|
||||
:modelValue="selectedProject.PROJCTSTR"
|
||||
@update:modelValue="selectedProject.PROJCTSTR = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="종료일"
|
||||
type="date"
|
||||
name="endDay"
|
||||
:modelValue="selectedProject.PROJCTEND"
|
||||
@update:modelValue="selectedProject.PROJCTEND = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="설명"
|
||||
name="description"
|
||||
:modelValue="selectedProject.PROJCTDES"
|
||||
@update:modelValue="selectedProject.PROJCTDES = $event"
|
||||
/>
|
||||
|
||||
<ArrInput
|
||||
title="주소"
|
||||
name="address"
|
||||
:is-essential="true"
|
||||
:is-row="true"
|
||||
:modelValue="{
|
||||
address: selectedProject.PROJCTARR,
|
||||
detailAddress: selectedProject.PROJCTDTL,
|
||||
postcode: selectedProject.PROJCTZIP
|
||||
}"
|
||||
@update:data="updateAddress"
|
||||
/>
|
||||
</template>
|
||||
<template #footer>
|
||||
<BackButton @click="closeEditModal" />
|
||||
<SaveButton @click="handleUpdate" />
|
||||
</template>
|
||||
</CenterModal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, onMounted, ref } from 'vue';
|
||||
import { defineProps, onMounted, ref, computed, inject } from 'vue';
|
||||
import UserList from '@c/user/UserList.vue';
|
||||
import CenterModal from '@c/modal/CenterModal.vue';
|
||||
import $api from '@api';
|
||||
import { KakaoMap, KakaoMapMarker } from 'vue3-kakao-maps';
|
||||
import BackBtn from '@c/button/BackBtn.vue';
|
||||
import BackButton from '@c/button/BackBtn.vue';
|
||||
import SaveButton from '@c/button/SaveBtn.vue';
|
||||
import EditBtn from '../button/EditBtn.vue';
|
||||
import DeleteBtn from '../button/DeleteBtn.vue';
|
||||
import FormInput from '@c/input/FormInput.vue';
|
||||
import FormSelect from '@c/input/FormSelect.vue';
|
||||
import ArrInput from '@c/input/ArrInput.vue';
|
||||
import { useToastStore } from '@s/toastStore';
|
||||
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
||||
import commonApi from '@/common/commonApi';
|
||||
|
||||
// 스토어
|
||||
const toastStore = useToastStore();
|
||||
const userStore = useUserInfoStore();
|
||||
|
||||
// Props 정의
|
||||
const props = defineProps({
|
||||
@ -120,39 +202,144 @@ const props = defineProps({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
addressZip: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
projctSeq: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
projctCol: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
projctColor: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
});
|
||||
|
||||
defineEmits(['click']);
|
||||
// Emit 정의
|
||||
const emit = defineEmits(['update']);
|
||||
|
||||
// 로그 모달 상태
|
||||
const isModalOpen = ref(false);
|
||||
const logData = ref(null);
|
||||
const logData = ref([]);
|
||||
|
||||
// 주소 팝오버 상태
|
||||
const isPopoverVisible = ref(false);
|
||||
const mapIconRef = ref(null);
|
||||
const coordinates = ref(null);
|
||||
|
||||
const fetchLogData = async () => {
|
||||
const response = await $api.get(`project/log/${props.projctSeq}`);
|
||||
logData.value = response.data.data.length > 0 ? response.data.data[0] : {};
|
||||
// 수정 모달 상태
|
||||
const isEditModalOpen = ref(false);
|
||||
const originalColor = ref('');
|
||||
const nameAlert = ref(false);
|
||||
const user = ref(null);
|
||||
|
||||
// 수정할 프로젝트 데이터
|
||||
const selectedProject = ref({
|
||||
PROJCTSEQ: props.projctSeq,
|
||||
PROJCTNAM: props.title,
|
||||
PROJCTSTR: props.strdate,
|
||||
PROJCTEND: props.enddate,
|
||||
PROJCTZIP: props.addressZip,
|
||||
PROJCTARR: props.address,
|
||||
PROJCTDTL: props.addressdtail,
|
||||
PROJCTDES: props.description,
|
||||
PROJCTCOL: props.projctCol,
|
||||
projctcolor: props.projctColor,
|
||||
});
|
||||
|
||||
// 컬러 목록 가져오기
|
||||
const { colorList } = commonApi({
|
||||
loadColor: true,
|
||||
colorType: 'YNP',
|
||||
});
|
||||
|
||||
// 기존 컬러 + 사용 가능 한 컬러
|
||||
const allColors = computed(() => {
|
||||
const existingColor = { value: selectedProject.value.PROJCTCOL, label: selectedProject.value.projctcolor };
|
||||
return [existingColor, ...colorList.value];
|
||||
});
|
||||
|
||||
// 수정 :: 주소
|
||||
const updateAddress = addressData => {
|
||||
selectedProject.value = {
|
||||
...selectedProject.value,
|
||||
PROJCTZIP: addressData.postcode,
|
||||
PROJCTARR: addressData.address,
|
||||
PROJCTDTL: addressData.detailAddress,
|
||||
};
|
||||
};
|
||||
|
||||
// 로그 데이터 가져오기
|
||||
const getLogData = async () => {
|
||||
const res = await $api.get(`project/log/${props.projctSeq}`);
|
||||
|
||||
logData.value = res.data.data;
|
||||
};
|
||||
|
||||
// 로그 모달 열기
|
||||
const openModal = async () => {
|
||||
await fetchLogData();
|
||||
await getLogData();
|
||||
isModalOpen.value = true;
|
||||
};
|
||||
|
||||
// 로그 모달 닫기
|
||||
const closeModal = () => {
|
||||
isModalOpen.value = false;
|
||||
};
|
||||
|
||||
// 수정 모달 열기
|
||||
const openEditModal = () => {
|
||||
isEditModalOpen.value = true;
|
||||
originalColor.value = props.projctCol;
|
||||
|
||||
// 사용자 정보 가져오기 (필요한 경우)
|
||||
if (!user.value) {
|
||||
userStore.userInfo().then(() => {
|
||||
user.value = userStore.user;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 수정 모달 닫기
|
||||
const closeEditModal = () => {
|
||||
isEditModalOpen.value = false;
|
||||
};
|
||||
|
||||
// 프로젝트 수정
|
||||
const handleUpdate = () => {
|
||||
nameAlert.value = selectedProject.value.PROJCTNAM.trim() === '';
|
||||
|
||||
if (nameAlert.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$api.patch('project/update', {
|
||||
projctSeq: selectedProject.value.PROJCTSEQ,
|
||||
projctNam: selectedProject.value.PROJCTNAM,
|
||||
projctCol: selectedProject.value.PROJCTCOL,
|
||||
projctArr: selectedProject.value.PROJCTARR,
|
||||
projctDtl: selectedProject.value.PROJCTDTL,
|
||||
projctZip: selectedProject.value.PROJCTZIP,
|
||||
projctStr: selectedProject.value.PROJCTSTR,
|
||||
projctEnd: selectedProject.value.PROJCTEND || null,
|
||||
projctDes: selectedProject.value.PROJCTDES || null,
|
||||
projctUmb: user.value?.name,
|
||||
originalColor: originalColor.value === selectedProject.value.PROJCTCOL ? null : originalColor.value,
|
||||
}).then(res => {
|
||||
if (res.status === 200) {
|
||||
toastStore.onToast('수정이 완료 되었습니다.', 's');
|
||||
closeEditModal();
|
||||
// 상위 컴포넌트에 업데이트 알림
|
||||
emit('update');
|
||||
window.location.reload()
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 주소를 좌표로 변환하는 함수
|
||||
const convertAddressToCoordinates = () => {
|
||||
@ -174,11 +361,27 @@ const convertAddressToCoordinates = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 컴포넌트 마운트 시 주소 변환
|
||||
onMounted(() => {
|
||||
// 프로젝트 삭제
|
||||
const handleDelete = () => {
|
||||
$api.patch('project/delete', {
|
||||
projctSeq: props.projctSeq,
|
||||
projctCol: props.projctCol,
|
||||
})
|
||||
.then(res => {
|
||||
if (res.status === 200) {
|
||||
toastStore.onToast('삭제가 완료되었습니다.', 's');
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
// 컴포넌트 마운트 시 실행
|
||||
onMounted(async () => {
|
||||
convertAddressToCoordinates();
|
||||
|
||||
// 사용자 정보 가져오기
|
||||
await userStore.userInfo();
|
||||
user.value = userStore.user;
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
|
||||
<template>
|
||||
<div @click="closeModal" class="modal fade scrollbar-none" :class="{ 'show': display, 'display-block': display , 'modal-back' : display }" id="modalCenter" tabindex="-1" aria-modal="true" role="dialog">
|
||||
<div @click="closeModal" class="modal fade scrollbar-none" :class="{ 'show': display , 'd-block': display , 'bg-dark bg-opacity-50' : display }" id="modalCenter" tabindex="-1" aria-modal="true" role="dialog">
|
||||
<div @click.stop class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title m-auto fw-bold" id="modalCenterTitle">
|
||||
<slot name="title">Modal Title</slot>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" @click="closeModal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<slot name="body">Modal body</slot>
|
||||
@ -21,26 +20,31 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
const prop = defineProps({
|
||||
display : {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
create: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['close']);
|
||||
const emit = defineEmits(['close' , 'reset']);
|
||||
|
||||
const closeModal = () => {
|
||||
emit('close' , false);
|
||||
if (prop.create) {
|
||||
emit('reset');
|
||||
}
|
||||
|
||||
emit('close', false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.modal-back {
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -122,5 +122,24 @@
|
||||
|
||||
|
||||
<style scoped>
|
||||
/* 모달 배경 투명하게 */
|
||||
.modal-dialog {
|
||||
background: none !important; /* 배경 제거 */
|
||||
box-shadow: none !important; /* 음영 제거 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 모달 내용 스타일 */
|
||||
.modal-content {
|
||||
background: #fff; /* 기존 흰색 배경 유지 */
|
||||
border-radius: 8px;
|
||||
box-shadow: none !important; /* 내부 음영 제거 */
|
||||
padding: 20px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -138,4 +138,25 @@ const closeModal = () => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
/* 모달 배경 투명하게 */
|
||||
.modal-dialog {
|
||||
background: none !important; /* 배경 제거 */
|
||||
box-shadow: none !important; /* 음영 제거 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 모달 내용 스타일 */
|
||||
.modal-content {
|
||||
background: #fff; /* 기존 흰색 배경 유지 */
|
||||
border-radius: 8px;
|
||||
box-shadow: none !important; /* 내부 음영 제거 */
|
||||
padding: 20px;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<SearchBar @update:data="search"/>
|
||||
<SearchBar @update:data="search" />
|
||||
<div class="d-flex align-items-center">
|
||||
<CategoryBtn :lists="yearCategory" @update:data="selectedCategory = $event" />
|
||||
<WriteBtn class="mt-2 ms-auto" @click="openCreateModal" />
|
||||
@ -11,7 +11,7 @@
|
||||
<p class="text-muted mt-4">등록된 프로젝트가 없습니다.</p>
|
||||
</div>
|
||||
|
||||
<div v-for="post in projectStore.projectList" :key="post.PROJCTSEQ" @click="openEditModal(post)" class="cursor-pointer">
|
||||
<div v-for="post in projectStore.projectList" :key="post.PROJCTSEQ">
|
||||
<ProjectCard
|
||||
:title="post.PROJCTNAM"
|
||||
:description="post.PROJCTDES"
|
||||
@ -19,14 +19,18 @@
|
||||
:enddate="post.PROJCTEND"
|
||||
:address="post.PROJCTARR"
|
||||
:addressdtail="post.PROJCTDTL"
|
||||
:addressZip="post.PROJCTZIP"
|
||||
:projctSeq="post.PROJCTSEQ"
|
||||
:projctCol="post.projctcolor"
|
||||
:projctCol="post.PROJCTCOL"
|
||||
:projctColor="post.projctcolor"
|
||||
@update="getProjectList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 등록 모달 -->
|
||||
<CenterModal :display="isCreateModalOpen" @close="closeCreateModal">
|
||||
<form @reset.prevent="formReset">
|
||||
<CenterModal :display="isCreateModalOpen" @close="closeCreateModal" :create="true" @reset="formReset">
|
||||
<template #title> 프로젝트 등록 </template>
|
||||
<template #body>
|
||||
<FormInput
|
||||
@ -34,6 +38,8 @@
|
||||
name="name"
|
||||
:is-essential="true"
|
||||
:is-alert="nameAlert"
|
||||
:modelValue="name"
|
||||
@update:alert="nameAlert = $event"
|
||||
@update:modelValue="name = $event"
|
||||
/>
|
||||
|
||||
@ -49,22 +55,25 @@
|
||||
|
||||
<FormInput
|
||||
title="시작 일"
|
||||
type="date"
|
||||
name="startDay"
|
||||
v-model="startDay"
|
||||
:type="'date'"
|
||||
:is-essential="true"
|
||||
:modelValue="startDay"
|
||||
v-model="startDay"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="종료 일"
|
||||
name="endDay"
|
||||
:type="'date'"
|
||||
name="endDay"
|
||||
:modelValue="endDay"
|
||||
@update:modelValue="endDay = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="설명"
|
||||
name="description"
|
||||
:modelValue="description"
|
||||
@update:modelValue="description = $event"
|
||||
/>
|
||||
|
||||
@ -74,303 +83,175 @@
|
||||
:isEssential="true"
|
||||
:is-row="true"
|
||||
:is-alert="addressAlert"
|
||||
:modelValue="addressData"
|
||||
@update:data="handleAddressUpdate"
|
||||
@update:alert="addressAlert = $event"
|
||||
/>
|
||||
</template>
|
||||
<template #footer>
|
||||
<BackButton @click="closeCreateModal" />
|
||||
<BackButton type="reset" @click="closeCreateModal" />
|
||||
<SaveButton @click="handleCreate" />
|
||||
</template>
|
||||
</CenterModal>
|
||||
|
||||
<!-- 수정 모달 -->
|
||||
<CenterModal :display="isEditModalOpen" @close="closeEditModal">
|
||||
<template #title> 프로젝트 수정 </template>
|
||||
<template #body>
|
||||
<FormInput
|
||||
title="이름"
|
||||
name="name"
|
||||
:is-essential="true"
|
||||
:is-alert="nameAlert"
|
||||
:modelValue="selectedProject.PROJCTNAM"
|
||||
@update:modelValue="selectedProject.PROJCTNAM = $event"
|
||||
/>
|
||||
|
||||
<FormSelect
|
||||
title="컬러"
|
||||
name="color"
|
||||
:is-essential="true"
|
||||
:is-label="true"
|
||||
:is-common="true"
|
||||
:data="allColors"
|
||||
:value="selectedProject.PROJCTCOL"
|
||||
@update:data="selectedProject.PROJCTCOL = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="시작일"
|
||||
type="date"
|
||||
name="startDay"
|
||||
:is-essential="true"
|
||||
:modelValue="selectedProject.PROJCTSTR"
|
||||
@update:modelValue="selectedProject.PROJCTSTR = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="종료일"
|
||||
type="date"
|
||||
name="endDay"
|
||||
:modelValue="selectedProject.PROJCTEND"
|
||||
@update:modelValue="selectedProject.PROJCTEND = $event"
|
||||
/>
|
||||
|
||||
<FormInput
|
||||
title="설명"
|
||||
name="description"
|
||||
:modelValue="selectedProject.PROJCTDES"
|
||||
@update:modelValue="selectedProject.PROJCTDES = $event"
|
||||
/>
|
||||
|
||||
<ArrInput
|
||||
title="주소"
|
||||
name="address"
|
||||
:is-essential="true"
|
||||
:is-row="true"
|
||||
:modelValue="selectedProject"
|
||||
@update:data="updateAddress"
|
||||
/>
|
||||
</template>
|
||||
<template #footer>
|
||||
<BackButton @click="closeEditModal" />
|
||||
<SaveButton @click="handleUpdate" />
|
||||
</template>
|
||||
</CenterModal>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, inject, ref, watch, onMounted } from 'vue';
|
||||
import SearchBar from '@c/search/SearchBar.vue';
|
||||
import ProjectCard from '@c/list/ProjectCard.vue';
|
||||
import CategoryBtn from '@c/category/CategoryBtn.vue';
|
||||
import WriteBtn from '@c/button/WriteBtn.vue';
|
||||
import CenterModal from '@c/modal/CenterModal.vue';
|
||||
import FormSelect from '@c/input/FormSelect.vue';
|
||||
import FormInput from '@c/input/FormInput.vue';
|
||||
import ArrInput from '@c/input/ArrInput.vue';
|
||||
import commonApi from '@/common/commonApi';
|
||||
import { useToastStore } from '@s/toastStore';
|
||||
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
||||
import { useProjectStore } from '@/stores/useProjectStore';
|
||||
import $api from '@api';
|
||||
import SaveButton from '@c/button/SaveBtn.vue';
|
||||
import BackButton from '@c/button/BackBtn.vue'
|
||||
import { computed, ref, watch, onMounted, inject } from 'vue';
|
||||
import SearchBar from '@c/search/SearchBar.vue';
|
||||
import ProjectCard from '@c/list/ProjectCard.vue';
|
||||
import CategoryBtn from '@c/category/CategoryBtn.vue';
|
||||
import WriteBtn from '@c/button/WriteBtn.vue';
|
||||
import CenterModal from '@c/modal/CenterModal.vue';
|
||||
import FormSelect from '@c/input/FormSelect.vue';
|
||||
import FormInput from '@c/input/FormInput.vue';
|
||||
import ArrInput from '@c/input/ArrInput.vue';
|
||||
import commonApi from '@/common/commonApi';
|
||||
import { useToastStore } from '@s/toastStore';
|
||||
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
||||
import { useProjectStore } from '@/stores/useProjectStore';
|
||||
import $api from '@api';
|
||||
import SaveButton from '@c/button/SaveBtn.vue';
|
||||
import BackButton from '@c/button/BackBtn.vue';
|
||||
|
||||
const dayjs = inject('dayjs');
|
||||
const today = dayjs().format('YYYY-MM-DD');
|
||||
const toastStore = useToastStore();
|
||||
const userStore = useUserInfoStore();
|
||||
const projectStore = useProjectStore();
|
||||
const toastStore = useToastStore();
|
||||
const userStore = useUserInfoStore();
|
||||
const projectStore = useProjectStore();
|
||||
|
||||
// 상태 관리
|
||||
const user = ref(null);
|
||||
const selectedCategory = ref(null);
|
||||
const searchText = ref('');
|
||||
// 상태 관리
|
||||
const user = ref(null);
|
||||
const selectedCategory = ref(null);
|
||||
const searchText = ref('');
|
||||
|
||||
// 등록 모달 상태
|
||||
const isCreateModalOpen = ref(false);
|
||||
const name = ref('');
|
||||
const color = ref('');
|
||||
const address = ref('');
|
||||
const detailAddress = ref('');
|
||||
const postcode = ref('');
|
||||
const startDay = ref(today);
|
||||
const endDay = ref('');
|
||||
const description = ref('');
|
||||
const nameAlert = ref(false);
|
||||
const addressAlert = ref(false);
|
||||
// dayjs 인스턴스 가져오기
|
||||
const dayjs = inject('dayjs');
|
||||
|
||||
// 수정 모달 상태
|
||||
const isEditModalOpen = ref(false);
|
||||
const originalColor = ref('');
|
||||
const selectedProject = ref({
|
||||
PROJCTSEQ: '',
|
||||
PROJCTNAM: '',
|
||||
PROJCTSTR: '',
|
||||
PROJCTEND: '',
|
||||
PROJCTZIP: '',
|
||||
PROJCTARR: '',
|
||||
PROJCTDTL: '',
|
||||
PROJCTDES: '',
|
||||
PROJCTCOL: '',
|
||||
projctcolor: '',
|
||||
});
|
||||
// 오늘 날짜를 YYYY-MM-DD 형식으로 변환
|
||||
const today = dayjs().format('YYYY-MM-DD');
|
||||
|
||||
// API 호출
|
||||
const { yearCategory, colorList } = commonApi({
|
||||
// 등록 모달 상태
|
||||
const isCreateModalOpen = ref(false);
|
||||
const name = ref('');
|
||||
const color = ref('');
|
||||
|
||||
const startDay = ref(today);
|
||||
const endDay = ref('');
|
||||
const description = ref('');
|
||||
const nameAlert = ref(false);
|
||||
const addressAlert = ref(false);
|
||||
|
||||
const addressData = ref({
|
||||
postcode: '',
|
||||
address: '',
|
||||
detailAddress: ''
|
||||
});
|
||||
|
||||
// API 호출
|
||||
const { yearCategory, colorList } = commonApi({
|
||||
loadColor: true,
|
||||
colorType: 'YNP',
|
||||
loadYearCategory: true,
|
||||
});
|
||||
});
|
||||
|
||||
// 검색 처리
|
||||
const search = async (searchKeyword) => {
|
||||
// 검색 처리
|
||||
const search = async searchKeyword => {
|
||||
searchText.value = searchKeyword.trim();
|
||||
await getProjectList();
|
||||
};
|
||||
};
|
||||
|
||||
const selectedYear = computed(() => {
|
||||
const selectedYear = computed(() => {
|
||||
if (!selectedCategory.value || selectedCategory.value === 900101) {
|
||||
return null;
|
||||
}
|
||||
// 선택된 category 값 label 값으로 변환
|
||||
return yearCategory.value.find(item => item.value === selectedCategory.value)?.label || null;
|
||||
});
|
||||
});
|
||||
|
||||
// 프로젝트 목록 조회
|
||||
const getProjectList = async () => {
|
||||
// 프로젝트 목록 조회
|
||||
const getProjectList = async () => {
|
||||
await projectStore.getProjectList(searchText.value, selectedYear.value);
|
||||
};
|
||||
};
|
||||
|
||||
// 카테고리 변경 감지
|
||||
watch(selectedCategory, async () => {
|
||||
// 카테고리 변경 감지
|
||||
watch(selectedCategory, async () => {
|
||||
await getProjectList();
|
||||
});
|
||||
});
|
||||
|
||||
// 등록 모달 관리
|
||||
const openCreateModal = () => {
|
||||
// 등록 모달 관리
|
||||
const openCreateModal = () => {
|
||||
isCreateModalOpen.value = true;
|
||||
};
|
||||
};
|
||||
|
||||
const closeCreateModal = () => {
|
||||
const closeCreateModal = () => {
|
||||
isCreateModalOpen.value = false;
|
||||
resetCreateForm();
|
||||
};
|
||||
};
|
||||
|
||||
const resetCreateForm = () => {
|
||||
const formReset = () => {
|
||||
name.value = '';
|
||||
color.value = '';
|
||||
address.value = '';
|
||||
detailAddress.value = '';
|
||||
postcode.value = '';
|
||||
addressData.value = {
|
||||
postcode: '',
|
||||
address: '',
|
||||
detailAddress: ''
|
||||
};
|
||||
startDay.value = today;
|
||||
endDay.value = '';
|
||||
description.value = '';
|
||||
nameAlert.value = false;
|
||||
addressAlert.value = false;
|
||||
}
|
||||
|
||||
// 등록 :: 주소 업데이트 핸들러
|
||||
const handleAddressUpdate = (data) => {
|
||||
addressData.value = data;
|
||||
};
|
||||
|
||||
// 등록 :: 주소 업데이트 핸들러
|
||||
const handleAddressUpdate = addressData => {
|
||||
address.value = addressData.address;
|
||||
detailAddress.value = addressData.detailAddress;
|
||||
postcode.value = addressData.postcode;
|
||||
};
|
||||
// 시작일이나 종료일이 변경될 때마다 종료일을 유효성 검사
|
||||
watch([startDay, endDay], () => {
|
||||
if (startDay.value && endDay.value) {
|
||||
const start = new Date(startDay.value);
|
||||
const end = new Date(endDay.value);
|
||||
|
||||
// 종료일이 시작일보다 이전 날짜라면 종료일을 시작일로 맞추기
|
||||
if (end < start) {
|
||||
endDay.value = startDay.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 프로젝트 등록
|
||||
const handleCreate = async () => {
|
||||
|
||||
// 프로젝트 등록
|
||||
const handleCreate = async () => {
|
||||
nameAlert.value = name.value.trim() === '';
|
||||
addressAlert.value = address.value.trim() === '';
|
||||
addressAlert.value = addressData.value.address.trim() === '';
|
||||
|
||||
if (nameAlert.value || addressAlert.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
$api.post('project/insert', {
|
||||
|
||||
projctNam: name.value,
|
||||
projctCol: color.value,
|
||||
projctStr: startDay.value,
|
||||
projctEnd: endDay.value || null,
|
||||
projctDes: description.value || null,
|
||||
projctArr: address.value,
|
||||
projctDtl: detailAddress.value,
|
||||
projctZip: postcode.value,
|
||||
projctArr: addressData.value.address,
|
||||
projctDtl: addressData.value.detailAddress,
|
||||
projctZip: addressData.value.postcode,
|
||||
projctCmb: user.value.name,
|
||||
})
|
||||
.then(res => {
|
||||
}).then(res => {
|
||||
if (res.status === 200) {
|
||||
toastStore.onToast('프로젝트가 등록되었습니다.', 's');
|
||||
closeCreateModal();
|
||||
getProjectList();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 수정 모달 관리
|
||||
const openEditModal = (post) => {
|
||||
isEditModalOpen.value = true;
|
||||
selectedProject.value = { ...post };
|
||||
originalColor.value = post.PROJCTCOL;
|
||||
};
|
||||
|
||||
const closeEditModal = () => {
|
||||
isEditModalOpen.value = false;
|
||||
};
|
||||
|
||||
// 기존 컬러 + 사용 가능 한 컬러
|
||||
const allColors = computed(() => {
|
||||
const existingColor = { value: selectedProject.value.PROJCTCOL, label: selectedProject.value.projctcolor };
|
||||
return [existingColor, ...colorList.value];
|
||||
});
|
||||
|
||||
// 변경된 내용 있는지 확인
|
||||
const hasChanges = computed(() => {
|
||||
const original = projectStore.projectList.find(p => p.PROJCTSEQ === selectedProject.value.PROJCTSEQ);
|
||||
if (!original) return false;
|
||||
|
||||
return (
|
||||
original.PROJCTNAM !== selectedProject.value.PROJCTNAM ||
|
||||
original.PROJCTCOL !== selectedProject.value.PROJCTCOL ||
|
||||
original.PROJCTARR !== selectedProject.value.PROJCTARR ||
|
||||
original.PROJCTDTL !== selectedProject.value.PROJCTDTL ||
|
||||
original.PROJCTZIP !== selectedProject.value.PROJCTZIP ||
|
||||
original.PROJCTSTR !== selectedProject.value.PROJCTSTR ||
|
||||
original.PROJCTEND !== selectedProject.value.PROJCTEND ||
|
||||
original.PROJCTDES !== selectedProject.value.PROJCTDES
|
||||
);
|
||||
});
|
||||
|
||||
// 수정 :: 주소
|
||||
const updateAddress = (addressData) => {
|
||||
selectedProject.value = {
|
||||
...selectedProject.value,
|
||||
PROJCTZIP: addressData.postcode,
|
||||
PROJCTARR: addressData.address,
|
||||
PROJCTDTL: addressData.detailAddress
|
||||
};
|
||||
};
|
||||
|
||||
// 프로젝트 수정
|
||||
const handleUpdate = () => {
|
||||
if (!hasChanges.value) {
|
||||
toastStore.onToast('변경된 내용이 없습니다.', 'e');
|
||||
return;
|
||||
}
|
||||
|
||||
$api.patch('project/update', {
|
||||
projctSeq: selectedProject.value.PROJCTSEQ,
|
||||
projctNam: selectedProject.value.PROJCTNAM,
|
||||
projctCol: selectedProject.value.PROJCTCOL,
|
||||
projctArr: selectedProject.value.PROJCTARR,
|
||||
projctDtl: selectedProject.value.PROJCTDTL,
|
||||
projctZip: selectedProject.value.PROJCTZIP,
|
||||
projctStr: selectedProject.value.PROJCTSTR,
|
||||
projctEnd: selectedProject.value.PROJCTEND || null,
|
||||
projctDes: selectedProject.value.PROJCTDES || null,
|
||||
projctUmb: user.value.name,
|
||||
originalColor: originalColor.value === selectedProject.value.PROJCTCOL ? null : originalColor.value
|
||||
}).then(res => {
|
||||
if (res.status === 200) {
|
||||
toastStore.onToast('수정이 완료 되었습니다.', 's');
|
||||
closeEditModal();
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
onMounted(async () => {
|
||||
await getProjectList();
|
||||
await userStore.userInfo();
|
||||
user.value = userStore.user;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="input-group mb-3 d-flex">
|
||||
<input type="text" class="form-control" placeholder="Search" @change="search" />
|
||||
<input type="text" class="form-control" placeholder="Search" @change="search" @input="preventLeadingSpace" />
|
||||
<button type="button" class="btn btn-primary"><i class="bx bx-search bx-md"></i></button>
|
||||
</div>
|
||||
</template>
|
||||
@ -15,11 +15,17 @@
|
||||
});
|
||||
|
||||
const emits = defineEmits(['update:data']);
|
||||
|
||||
const search = function (event) {
|
||||
|
||||
//Type Number 일때 maxlength 적용 안됨 방지
|
||||
if (event.target.value.length > props.maxlength) {
|
||||
event.target.value = event.target.value.slice(0, props.maxlength);
|
||||
}
|
||||
emits('update:data', event.target.value);
|
||||
};
|
||||
|
||||
const preventLeadingSpace = function (event) {
|
||||
event.target.value = event.target.value.trimStart();
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
<strong class="mx-2 w-75">{{ item.WRDDICTTL }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-5" v-html="$common.contentToHtml(item.WRDDICCON)"></p>
|
||||
<p class="mt-5 dict-content-wrap" v-html="$common.contentToHtml(item.WRDDICCON)"></p>
|
||||
<div class="d-flex justify-content-between flex-wrap gap-2 mb-2">
|
||||
<div class="d-flex flex-wrap align-items-center mb-50">
|
||||
<div class="avatar avatar-sm me-2">
|
||||
@ -40,7 +40,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-0 small fw-medium">{{ formattedDate(item.author.createdAt) }}</p>
|
||||
<p class="mb-0 small fw-medium">{{ $common.dateFormatter(item.author.createdAt) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -59,7 +59,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-0 small fw-medium">{{ formattedDate(item.lastEditor.updatedAt) }}</p>
|
||||
<p class="mb-0 small fw-medium">{{ $common.dateFormatter(item.lastEditor.updatedAt) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -78,7 +78,6 @@ import { ref, toRefs, getCurrentInstance, } from 'vue';
|
||||
import EditBtn from '@/components/button/EditBtn.vue';
|
||||
import $api from '@api';
|
||||
import DictWrite from './DictWrite.vue';
|
||||
import { formattedDate } from "@/common/formattedDate";
|
||||
import { useUserInfoStore } from '@s/useUserInfoStore';
|
||||
import { useWriteVisibleStore } from '@s/writeVisible';
|
||||
|
||||
|
||||
@ -170,8 +170,10 @@ const saveWord = () => {
|
||||
|
||||
// 내용 확인
|
||||
let inserts = [];
|
||||
if(inserts.length === 0 && content.value?.ops?.length > 0){
|
||||
inserts = content.value.ops.map(op => op.insert.trim());
|
||||
if (inserts.length === 0 && content.value?.ops?.length > 0) {
|
||||
inserts = content.value.ops.map(op =>
|
||||
typeof op.insert === 'string' ? op.insert.trim() : op.insert
|
||||
);
|
||||
}
|
||||
|
||||
// 내용 체크
|
||||
|
||||
@ -12,19 +12,16 @@ import $api from '@api';
|
||||
export const useProjectStore = defineStore('project', () => {
|
||||
const projectList = ref([]);
|
||||
|
||||
const getProjectList = async (searchText, selectedYear) => {
|
||||
try {
|
||||
const getProjectList = async (searchText = '', selectedYear = '') => {
|
||||
const res = await $api.get('project/select', {
|
||||
params: {
|
||||
searchKeyword: searchText,
|
||||
category: selectedYear,
|
||||
searchKeyword: searchText || '',
|
||||
category: selectedYear || '',
|
||||
},
|
||||
});
|
||||
projectList.value = res.data.data.projectList;
|
||||
} catch (error) {
|
||||
console.error('프로젝트 목록 조회 실패:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return { projectList, getProjectList };
|
||||
});
|
||||
|
||||
@ -536,5 +536,9 @@ watch([holidayDates, lastRemainingYear, lastRemainingMonth], () => {
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
/* 모달 본문 스크롤 */
|
||||
.modal-body {
|
||||
max-height: 130px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -230,7 +230,7 @@
|
||||
// isWriteVisible.value = false;
|
||||
writeStore.closeAll();
|
||||
getwordList();
|
||||
const newCategory = { label: data, value: category }; // 여기서 data 사용
|
||||
const newCategory = { label: data, value: category };
|
||||
cateList.value = [newCategory, ...cateList.value];
|
||||
}
|
||||
});
|
||||
@ -244,7 +244,7 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// 체크 상태 업데이트
|
||||
|
||||
Loading…
Reference in New Issue
Block a user