유틸추가

This commit is contained in:
ckx6954 2024-12-21 19:13:34 +09:00
parent 9cefae6525
commit 4f7d21fdef
6 changed files with 344 additions and 1 deletions

14
package-lock.json generated
View File

@ -20,9 +20,11 @@
"dayjs": "^1.11.13",
"flatpickr": "^4.6.13",
"front": "file:",
"heic2any": "^0.0.4",
"pinia": "^2.2.6",
"pinia-plugin-persist": "^1.0.0",
"quill": "^2.0.3",
"upload-images-converter": "^2.0.2",
"vue": "^3.5.13",
"vue-flatpickr-component": "^11.0.5",
"vue-router": "^4.4.5"
@ -2977,6 +2979,12 @@
"node": ">= 0.4"
}
},
"node_modules/heic2any": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/heic2any/-/heic2any-0.0.4.tgz",
"integrity": "sha512-3lLnZiDELfabVH87htnRolZ2iehX9zwpRyGNz22GKXIu0fznlblf0/ftppXKNqS26dqFSeqfIBhAmAj/uSp0cA==",
"license": "MIT"
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
@ -4247,6 +4255,12 @@
"browserslist": ">= 4.21.0"
}
},
"node_modules/upload-images-converter": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/upload-images-converter/-/upload-images-converter-2.0.2.tgz",
"integrity": "sha512-cltVwZ+RU70Qx8heZrSj8OpQhR9mFHZ6CXudosKkFlM91Iiznl8Oluw/x+9DTnSKkvipvkf1oCvyVw5UPIpZ1Q==",
"license": "MIT"
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",

View File

@ -23,9 +23,11 @@
"dayjs": "^1.11.13",
"flatpickr": "^4.6.13",
"front": "file:",
"heic2any": "^0.0.4",
"pinia": "^2.2.6",
"pinia-plugin-persist": "^1.0.0",
"quill": "^2.0.3",
"upload-images-converter": "^2.0.2",
"vue": "^3.5.13",
"vue-flatpickr-component": "^11.0.5",
"vue-router": "^4.4.5"

View File

@ -1 +1,104 @@
.app-calendar-wrapper{position:relative;border-radius:.375rem}.app-calendar-wrapper .app-calendar-sidebar{position:absolute;overflow:hidden;flex-grow:0;flex-basis:18.75rem;left:calc(-18.75rem - 1.2rem);height:100%;width:18.75rem;transition:all .2s;z-index:4}.app-calendar-wrapper .app-calendar-sidebar.show{left:0}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar{box-shadow:none}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-month,.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekday,.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekdays{background:rgba(0,0,0,0)}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-days{border:0}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar:focus{outline:0}.app-calendar-wrapper .app-calendar-content{position:relative}.app-calendar-wrapper .fc-toolbar h2{font-size:1.5rem;line-height:2.375rem}@media(max-width: 767.98px){.app-calendar-wrapper .fc-toolbar h2{font-size:1rem}}.app-calendar-wrapper .fc-toolbar-chunk{overflow:auto}.app-calendar-wrapper table.fc-scrollgrid{border-left:0;border-right:0}.app-calendar-wrapper table.fc-scrollgrid th,.app-calendar-wrapper table.fc-scrollgrid td{border-right:0}.app-calendar-wrapper .fc-timeGridDay-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td,.app-calendar-wrapper .fc-timeGridWeek-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td{border-bottom:0}.app-calendar-wrapper .fc-dayGridMonth-view table.fc-scrollgrid td{border-bottom:0 !important}.app-calendar-wrapper .fc-header-toolbar{margin-bottom:1.5rem !important}.app-calendar-wrapper .fc-view-container{margin:0 -1.6rem}.app-calendar-wrapper .event-sidebar .ql-editor{min-height:5rem}.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice{display:flex}.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice .avatar{display:none}@media(min-width: 992px){.app-calendar-wrapper .app-calendar-sidebar{position:static;height:auto;background-color:rgba(0,0,0,0) !important}.app-calendar-wrapper .app-calendar-sidebar .flatpickr-days{background-color:rgba(0,0,0,0)}}[dir=rtl] .app-calendar-wrapper .fc .fc-toolbar .fc-sidebarToggle-button{order:1}[dir=rtl] .app-calendar-wrapper .app-calendar-sidebar{left:auto;right:calc(-18.75rem - 1.2rem)}[dir=rtl] .app-calendar-wrapper .app-calendar-sidebar.show{left:auto;right:0}.light-style .app-calendar-wrapper .app-calendar-sidebar{background-color:#fff}.dark-style .app-calendar-wrapper .app-calendar-sidebar{background-color:#2b2c40}
.app-calendar-wrapper {
position: relative;
border-radius: 0.375rem;
}
.app-calendar-wrapper .app-calendar-sidebar {
position: absolute;
overflow: hidden;
flex-grow: 0;
flex-basis: 18.75rem;
left: calc(-18.75rem - 1.2rem);
height: 100%;
width: 18.75rem;
transition: all 0.2s;
z-index: 4;
}
.app-calendar-wrapper .app-calendar-sidebar.show {
left: 0;
}
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar {
box-shadow: none;
}
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-month,
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekday,
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-weekdays {
background: rgba(0, 0, 0, 0);
}
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar .flatpickr-days {
border: 0;
}
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-calendar:focus {
outline: 0;
}
.app-calendar-wrapper .app-calendar-content {
position: relative;
}
.app-calendar-wrapper .fc-toolbar h2 {
font-size: 1.5rem;
line-height: 2.375rem;
}
@media (max-width: 767.98px) {
.app-calendar-wrapper .fc-toolbar h2 {
font-size: 1rem;
}
}
.app-calendar-wrapper .fc-toolbar-chunk {
overflow: auto;
}
.app-calendar-wrapper table.fc-scrollgrid {
border-left: 0;
border-right: 0;
}
.app-calendar-wrapper table.fc-scrollgrid th,
.app-calendar-wrapper table.fc-scrollgrid td {
border-right: 0;
}
.app-calendar-wrapper .fc-timeGridDay-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td,
.app-calendar-wrapper .fc-timeGridWeek-view table.fc-scrollgrid tbody tr:not(.fc-scrollgrid-section:first-of-type) td {
border-bottom: 0;
}
.app-calendar-wrapper .fc-dayGridMonth-view table.fc-scrollgrid td {
border-bottom: 0 !important;
}
.app-calendar-wrapper .fc-header-toolbar {
margin-bottom: 1.5rem !important;
}
.app-calendar-wrapper .fc-view-container {
margin: 0 -1.6rem;
}
.app-calendar-wrapper .event-sidebar .ql-editor {
min-height: 5rem;
}
.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice {
display: flex;
}
.app-calendar-wrapper .event-sidebar .select2 .select2-selection__choice .avatar {
display: none;
}
@media (min-width: 992px) {
.app-calendar-wrapper .app-calendar-sidebar {
position: static;
height: auto;
background-color: rgba(0, 0, 0, 0) !important;
}
.app-calendar-wrapper .app-calendar-sidebar .flatpickr-days {
background-color: rgba(0, 0, 0, 0);
}
}
[dir='rtl'] .app-calendar-wrapper .fc .fc-toolbar .fc-sidebarToggle-button {
order: 1;
}
[dir='rtl'] .app-calendar-wrapper .app-calendar-sidebar {
left: auto;
right: calc(-18.75rem - 1.2rem);
}
[dir='rtl'] .app-calendar-wrapper .app-calendar-sidebar.show {
left: auto;
right: 0;
}
.light-style .app-calendar-wrapper .app-calendar-sidebar {
background-color: #fff;
}
.dark-style .app-calendar-wrapper .app-calendar-sidebar {
background-color: #2b2c40;
}

View File

@ -4,6 +4,7 @@ import router from "@/router/index";
const $api = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 300000,
withCredentials : true
})
/**

View File

@ -0,0 +1,129 @@
/**
image to webp
@사용법
const webpFile = await convertImageToWebp(this.attach);
attach = webpFile[0];
*/
import heic2any from 'heic2any';
import { imageConverter } from 'upload-images-converter';
const calculateAspectRatioSize = (originWidth, originHeight, maxWidthOrHeight) => {
const maxSize = Math.max(originWidth, originHeight);
if (maxSize <= maxWidthOrHeight) {
return { width: originWidth, height: originHeight };
}
if (originWidth === maxSize) {
const width = maxWidthOrHeight;
const height = Number(((originHeight * maxWidthOrHeight) / originWidth).toFixed(1));
return { width, height };
}
const width = Number(((originWidth * maxWidthOrHeight) / originHeight).toFixed(1));
const height = maxWidthOrHeight;
return { width, height };
};
const getImageSize = (imageFile) => {
return new Promise((resolve, reject) => {
if (!imageFile) {
resolve({ originWidth: 100, originHeight: 100 }); // Default size
return;
}
const img = new Image();
const reader = new FileReader();
img.onload = () => {
const originWidth = img.naturalWidth;
const originHeight = img.naturalHeight;
resolve({ originWidth, originHeight });
};
reader.onload = () => {
img.src = reader.result?.toString() ?? '';
};
reader.readAsDataURL(imageFile);
img.onerror = error => {
reject(error);
};
reader.onerror = error => {
reject(error);
};
});
};
const convertImageToWebp = async (imageFile) => {
if (typeof imageFile === 'string' || imageFile.name.split('.')[1].toLowerCase() === 'webp') {
return imageFile;
}
if (!imageFile || !(imageFile instanceof Blob)) {
const placeholderBlob = new Blob([], { type: 'image/webp' });
const placeholderFile = new File([placeholderBlob], `${Date.now().toString()}.webp`);
const dataTransfer = new DataTransfer();
dataTransfer.items.add(placeholderFile);
return dataTransfer.files;
}
const fileExtension = imageFile.name.split('.').pop().toLowerCase();
if (fileExtension === 'heic') {
try {
const webpBlob = await heic2any({
blob: imageFile,
toType: 'image/webp',
quality: 0.8,
});
const { originWidth, originHeight } = await getImageSize(webpBlob);
const maxWidthOrHeight = 1200;
const { width, height } = calculateAspectRatioSize(originWidth, originHeight, maxWidthOrHeight);
const compressedBlob = await imageConverter({ files: [webpBlob], width, height });
const outputWebpFile = new File([compressedBlob[0]], `${Date.now().toString()}.webp`);
const dataTransfer = new DataTransfer();
dataTransfer.items.add(outputWebpFile);
return dataTransfer.files;
} catch (error) {
console.error('HEIC 변환 오류:', error);
throw error;
} finally {
// 로딩있으면 여기서 끝
}
} else {
try {
const { originWidth, originHeight } = await getImageSize(imageFile);
const maxWidthOrHeight = 1200;
const { width, height } = calculateAspectRatioSize(originWidth, originHeight, maxWidthOrHeight);
const compressedBlob = await imageConverter({ files: [imageFile], width, height });
const outputWebpFile = new File([compressedBlob[0]], `${Date.now().toString()}.webp`);
const dataTransfer = new DataTransfer();
dataTransfer.items.add(outputWebpFile);
return dataTransfer.files;
} catch (error) {
console.error('HEIC 변환 오류:', error);
throw error;
} finally {
// 로딩있으면 여기서 끝
}
}
};
export { convertImageToWebp };

View File

@ -5,3 +5,97 @@ export const isEmpty = (value) => {
return true;
return false;
}
export const isPC = () => {
const varUA = navigator.userAgent.toLowerCase();
const isMobile = /iphone|ipad|ipod|android|blackberry|iemobile|opera mini/i.test(varUA);
return !isMobile;
}
export const returnMimeTypes = (extension) => {
const mimeTypes = {
// Archive
'7z': 'application/x-7z-compressed',
'gz': 'application/gzip',
'tar': 'application/x-tar',
'zip': 'application/zip',
// Audio
'aac': 'audio/aac',
'mp3': 'audio/mpeg',
'ogg': 'audio/ogg',
'opus': 'audio/opus',
'wav': 'audio/wav',
'webm': 'audio/webm',
// Image
'bmp': 'image/bmp',
'gif': 'image/gif',
'ico': 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'png': 'image/png',
'svg': 'image/svg+xml',
'tiff': 'image/tiff',
'webp': 'image/webp',
// Video
'avi': 'video/x-msvideo',
'mp4': 'video/mp4',
'mpeg': 'video/mpeg',
'ogg': 'video/ogg',
'webm': 'video/webm',
'mov': 'video/quicktime',
'wmv': 'video/x-ms-wmv',
// Document
'doc': 'application/msword',
'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'epub': 'application/epub+zip',
'html': 'text/html',
'htm': 'text/html',
'odt': 'application/vnd.oasis.opendocument.text',
'pdf': 'application/pdf',
'ppt': 'application/vnd.ms-powerpoint',
'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'rtf': 'application/rtf',
'txt': 'text/plain',
'xls': 'application/vnd.ms-excel',
'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xml': 'application/xml',
'json': 'application/json',
'csv': 'text/csv',
// Code / Script
'css': 'text/css',
'js': 'text/javascript',
'json': 'application/json',
'php': 'application/x-httpd-php',
'xml': 'application/xml',
// Font
'woff': 'font/woff',
'woff2': 'font/woff2',
'ttf': 'font/ttf',
'otf': 'font/otf',
// Web
'jsonld': 'application/ld+json',
'webmanifest': 'application/manifest+json',
// Others
'bin': 'application/octet-stream',
'exe': 'application/octet-stream',
'apk': 'application/vnd.android.package-archive',
'dll': 'application/x-msdownload',
'iso': 'application/x-iso9660-image',
'msi': 'application/x-msi',
'torrent': 'application/x-bittorrent',
// Unknown
'default': 'application/octet-stream'
}
const ext = extension.trim().toLowerCase();
return mimeTypes[ext] || mimeTypes['default'];
};