Files
PM_test/views/main/jsm/archive/common.js
2026-06-15 16:10:05 +09:00

513 lines
18 KiB
JavaScript

import { vars } from './variable.js';
// 파일 사이즈 변환
export function formatBytes(bytes) {
const abs = Math.abs(bytes);
let size, unit;
if (abs < 1024) {
size = addCommasToNumber(bytes);
unit = ' Bytes';
} else if (abs < 1048576) {
size = addCommasToNumber((bytes / 1024).toFixed(2));
unit = ' KB';
} else if (abs < 1073741824) {
size = addCommasToNumber((bytes / 1048576).toFixed(2));
unit = ' MB';
} else if (abs < 1099511627776) {
size = addCommasToNumber((bytes / 1073741824).toFixed(2));
unit = ' GB';
} else {
size = addCommasToNumber((bytes / 1099511627776).toFixed(2));
unit = ' TB';
}
if (size != 0) {
let decimalPointNum = size.split('.')[1];
if (decimalPointNum) {
// 소수점 아래 숫자가 00인 경우
if (decimalPointNum == '00') size = size.split('.')[0];
// 소수점 아래 두번째 숫자가 0인 경우
else if (decimalPointNum[1] == '0') size = `${size.split('.')[0]}.${decimalPointNum[0]}`;
}
}
return size + unit;
}
// 1000 단위 콤마 추가
// export function addCommasToNumber(num) {
// return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }
export function addCommasToNumber(num) {
const isNegative = Number(num) < 0;
const parts = Math.abs(Number(num)).toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
const formatted = parts.join('.');
return isNegative ? `-${formatted}` : formatted;
}
export function getDepth(path) {
path = path.startsWith('/') ? path.slice(1) : path;
let pathSplit = path.split('/');
let result = pathSplit.length;
return result;
}
export function updatePartialPath(sourcePath, targetPath) {
let sourcePathSplit = sourcePath.split('/');
let targetPathSplit = targetPath.split('/');
for (let i = 0; i < sourcePathSplit.length; i++) {
targetPathSplit[i] = sourcePathSplit[i];
}
return targetPathSplit.join('/');
}
// 파일명, 확장자 분리
export function splitBaseAndExt(target, isLowerExt) {
let targetSplit = target.split('.');
let ext = targetSplit.pop();
if (isLowerExt) ext = ext.toLowerCase();
let base = targetSplit.join('.');
return { ext: ext, base: base }
}
// 선택한 대상이 포함된 상위 폴더 경로 추출
export function splitTopPathAndTargetName(resourcePath) {
let resourcePathSplit = resourcePath.split('/');
let targetName = resourcePathSplit.pop();
let topPath = resourcePathSplit.join('/');
if (!topPath || topPath == '' || topPath == null) topPath = '/';
return { targetName: targetName, topPath: topPath };
}
export function extractPathByLength(target, count) {
if (!Array.isArray(target)) {
target = target.split('/');
}
const parts = target.filter(Boolean).slice(0, count);
return '/' + parts.join('/');
}
// 특수문자를 체크하는 정규표현식
export function hasSpecialChar(target) {
// const pattern = /[\/\\;:?`'"<>|#%&*]/;
const pattern = /[\/\\:*?'"`<>|#]/;
return pattern.test(target);
}
// 동일한 폴더명/파일명 존재 여부 확인
export function existEqualName(type, comparisonPath, targetName) {
let result;
if (comparisonPath != '' && comparisonPath != undefined) {
result = getTypeDataFromFolderData(type, comparisonPath)[targetName];
} else {
// result = vars.currentTreeObject[type][targetName];
result = vars.allTreeObject[type][targetName];
}
// 헤더 버튼 이름 변경 시 페이지 버튼과 이름 같은 경우 변경 불가
let pageBtnNameArr = ['과업개요', '공문'];
if (comparisonPath == '/' && result == undefined) result = pageBtnNameArr.includes(targetName);
return result;
// folderData에서 타입(폴더/파일)과 경로를 사용해서 해당 경로의 타입별 데이터 가져오기
function getTypeDataFromFolderData(type, path) {
let data;
if (type == 'folder') data = vars.allTreeObject[type];
if (type == 'file') data = vars.currentTreeObject[type];
let pathSplit = path.split('/');
pathSplit.shift();
// if (pathSplit[0] == '') return data;
for (let i = 0; i < pathSplit.length; i++) {
if (data[pathSplit[i]]) {
if (type == 'folder') data = data[pathSplit[i]]['child'][type];
if (type == 'file') data = data;
} else {
data = data;
}
}
return data;
}
}
export function getNextFileName(nameArr, newName) {
const dotIdx = newName.lastIndexOf('.');
const base = dotIdx !== -1 ? newName.slice(0, dotIdx) : newName;
const ext = dotIdx !== -1 ? newName.slice(dotIdx) : '';
const set = new Set(nameArr);
let maxNum = 0;
const regex = new RegExp(`^${escapeRegExp(base)}(?: \\((\\d+)\\))?${escapeRegExp(ext)}$`);
for (const name of set) {
const match = name.match(regex);
if (match) {
const num = match[1] ? parseInt(match[1], 10) : 0;
if (num > maxNum) maxNum = num;
}
}
if (maxNum === 0 && !set.has(newName)) return newName;
return `${base} (${maxNum + 1})${ext}`;
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
}
export function getDataFromTreeObject(path, type, data) {
let parentData;
if (!data) data = vars.allTreeObject;
let pathSplit = path.split('/');
pathSplit.shift();
for (let i = 0; i < pathSplit.length; i++) {
if (i != pathSplit.length - 1) {
if (data['folder'][pathSplit[i]]) {
data = data['folder'][pathSplit[i]]['child'];
}
} else {
if (type == 'folder') {
parentData = data;
data = data['folder'][pathSplit[i]];
}
if (type == 'file') {
if (data['file'][pathSplit[i]]) {
parentData = data;
data = data['file'][pathSplit[i]];
}
}
}
}
return { parentData: parentData, data: data };
}
export function getCurrentTreeObject(path) {
let data = vars.allTreeObject;
let pathSplit = path.split('/');
pathSplit.shift();
for (let i = 0; i < pathSplit.length; i++) {
if (i != pathSplit.length - 1) {
if (data['folder'][pathSplit[i]]) {
data = data['folder'][pathSplit[i]]['child'];
}
} else {
if (data['folder'][pathSplit[i]]) data = data['folder'][pathSplit[i]]['child'];
}
}
return data;
}
export function targetFocus(target, behavior = 'smooth') {
target.scrollIntoView({
behavior: behavior, // 부드럽게
block: 'center', // 화면 중앙에 위치하도록 (start, end, nearest 도 가능)
inline: 'center'
});
target.focus();
}
export function pxToRem(px) {
let remPx = parseFloat(getComputedStyle(document.documentElement).fontSize);
return px / remPx;
}
export function buildResourcePathFromSegments(rows) {
if (!Array.isArray(rows)) rows = [rows];
let result = [];
rows.map(row => {
let resourcePath = '/';
let maxDepth = 8;
let arr = [];
for (let i = 0; i < maxDepth; i++) {
let num = i+1;
let segment = row[`path${num}`];
if (segment) arr.push(segment);
}
if (arr.length != 0) resourcePath += arr.join('/');
result.push(resourcePath);
})
return result;
}
export function headerBtnForceClick(headerBtn) {
headerBtn.click();
}
export function treeBtnForceClick(treeBtn) {
treeBtn.click();
}
export function closeInitProgress() {
document.querySelector('.init-progress').style.display = 'none';
}
export async function getMyDownloadList(){
let res = await axios.get(`${vars.path_name}/getMyDownloadList`, {params : {user_id : JSON.parse(vars.userInfoString).user_id}});
// console.log(res.data);
if(res.data.length > 0){
if(document.querySelector('.download-btn .download-reddot')){
document.querySelector('.download-btn .download-reddot').style.display = 'block';
}
}else{
if(document.querySelector('.download-btn .download-reddot')){
document.querySelector('.download-btn .download-reddot').style.display = 'none';
}
}
let ul = document.querySelector('.download-modal__body_list');
ul.innerHTML = '';
for(let i = 0; i < res.data.length; i++){
let li = document.createElement('li');
li.classList.add('download-modal__body_list_item');
let expireDate = new Date(res.data[i].expire_date);
let now = new Date();
let yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
let state = (expireDate < yesterday)? `<img class="--button__xsmall-icon --disable" src="/main/img/archive/icon__download--111.svg" alt="/" />`: (!res.data[i].made)?`준비중`:`<img class="--button__xsmall-icon downloadFolder__btn__icon" src="/main/img/archive/icon__download--111.svg" alt="/" />`
let expire =(state == '준비중')?state :(expireDate < yesterday)? '만료됨': formatDateTime(expireDate);
li.innerHTML = `
<img class="--icon" src="/main/img/header/header-folder-icon.svg" alt="/" />
<div class="download-modal__body_list_item_text">
<h4 class="download-modal__body_list_item_text_title">
${res.data[i].name}
</h4>
<p class="download-modal__body_list_item_text_subtitle">
${res.data[i].project_nm}${res.data[i].path}
</p>
</div>
<h6 class="download-modal__body_list_item_time">
${expire}
</h6>
<div class="download-modal__body_list_item_status">${state}</div>
`;
ul.appendChild(li);
li.querySelector('.downloadFolder__btn__icon')?.addEventListener('click', () => {
window.location.href = res.data[i].url;
})
}
function formatDateTime(date) {
const padZero = (num) => String(num).padStart(2, '0');
const year = date.getFullYear();
const month = padZero(date.getMonth() + 1); // getMonth()는 0부터 시작하므로 +1
const day = padZero(date.getDate());
const hours = padZero(date.getHours());
const minutes = padZero(date.getMinutes());
return `${year}-${month}-${day} ${hours}:${minutes}`;
}
}
export async function openNewWindowViewer() {
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
let lastListItem = (isRecycleBinModal) ? vars.lastListItem_bin : vars.lastListItem;
let resourcePath = lastListItem.dataset.resourcePath;
let dataId = lastListItem.dataset.id;
let isLowerExt = true, ext = splitBaseAndExt(resourcePath, isLowerExt).ext;
let thumbnail_key = getDataFromTreeObject(resourcePath, 'file', vars.currentTreeObject).data?.thumbnailKey;
//Presigned URL
let PresignedUrl = undefined;
let getDataInfoParams = {
userInfoString: vars.userInfoString,
storageType: vars.storageType,
dataIdArr: [dataId],
isRemoved: isRecycleBinModal,
debug: "'우측 미리보기 새 창으로 열기 버튼 클릭 이벤트'에서 실행"
}
let getDataInfoRes = await axios.post(`${vars.path_name}/getDataInfo`, { params: getDataInfoParams } );
if (getDataInfoRes.data.message == 'getDataInfo_success') {
let result = getDataInfoRes.data.result;
let directViewExtArr = ['xls', 'xlsx', 'xlsm', 'docx', 'hwp', 'hwpx'];
let objectKey = directViewExtArr.includes(ext) ? result.object_key : result.popup_key;
if(objectKey == undefined || objectKey == `` || objectKey == null){
return;
}
let generateDownloadUrlParams = {
objectKey: objectKey,
resourcePath: resourcePath
}
let generateDownloadUrlRes = await axios.post(`${vars.path_name}/generateDownloadUrl`, generateDownloadUrlParams);
if (generateDownloadUrlRes.data.message == 'generateDownloadUrl_success') {
PresignedUrl = generateDownloadUrlRes.data.url;
}
}
//Presigned URL end
thumbnail_key = encodeURIComponent(thumbnail_key);
resourcePath = encodeURIComponent(resourcePath);
let fullPath = encodeURIComponent(PresignedUrl);
// 뷰어 기본 width값은 현재 화면 width값의 절반
let denominator = 2;
// url 뷰어는 현재 화면 width값과 동일하게 설정
if (ext == 'url') denominator = 1;
let width = screen.width / denominator;
let height = screen.height;
let left = screen.width * 2 + 10;
let open_ext = `pdf`;
switch(ext){
case 'pdf' :
case 'doc' :
case 'ppt' :
case 'pptx' :
case 'dwg' :
case 'dxf' :
case 'grm' :
open_ext = 'pdf';
break;
case 'hwp' :
case 'hwpx' :
open_ext = ext;
break;
case 'xls' :
case 'xlsx' :
case 'xlsm' :
open_ext = ext;
break;
case 'docx' :
open_ext = ext;
break;
case 'gsim' :
open_ext = 'gsim';
break
case 'ifc' :
open_ext = 'ifc';
break
case 'png' :
case 'jpg' :
case 'jpeg' :
case 'webp' :
case 'gif' :
open_ext = 'png';
break
case 'mp4' :
case 'mov' :
case 'webm' :
open_ext = 'mp4';
break
case 'log' :
case 'txt' :
case 'md' :
open_ext = 'txt';
break
case 'url' :
open_ext = 'url';
break;
case 'zip' :
open_ext = 'zip';
break
case 'glb':
case 'gltf':
case 'obj':
case 'stl':
case 'fbx':
case '3dm':
open_ext = 'glb';
break;
case 'html':
open_ext = 'html';
break;
}
//presigned url은 ext를 읽을수 없엉...
const jsonData = JSON.stringify({$ext : open_ext});
const encodedData = btoa(jsonData);
// 3d모델뷰어 썸네일 생성을 위해 dataId, path_name 추가
// let popup = window.open(`/popup?path=${fullPath}&data=${encodedData}`, '', `width=${width}, height=${height}, left=${left},`);
let popup = window.open(`/popup?thumbnail_key=${thumbnail_key}&path_name=${vars.path_name}&resourcePath=${resourcePath}&dataId=${dataId}&path=${fullPath}&data=${encodedData}`, '', `width=${width}, height=${height}, left=${left},`);
}
export function initFileAreaUI(fileAreaMode) {
let listContainer = document.querySelector('.archive-main .archive-main-center .list-container');
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
if (isRecycleBinModal) listContainer = document.querySelector('.recycle-bin-modal .recycle-bin-wrap .list-container');
let listHeader = listContainer.querySelector('.list-header');
let listBody = listContainer.querySelector('.list-body');
let listBodyItemWrap = listBody.querySelector('.list-item-wrap');
let mapContainer = listBody.querySelector('.map-container');
let archiveMainRight = document.querySelector('.archive-main-right');
let viewerHeader = archiveMainRight.querySelector('.viewer-header');
if (fileAreaMode == 'map') {
listHeader.style.display = 'none';
listBody.style.height = '100%';
listBody.style.overflowY = 'hidden';
listBodyItemWrap.style.display = 'none';
if (mapContainer) mapContainer.style.display = 'flex';
archiveMainRight.style.minWidth = '36rem';
archiveMainRight.style.maxWidth = '36rem';
archiveMainRight.style.height = 'calc(100% - 2.75rem)';
archiveMainRight.style.position = 'absolute';
archiveMainRight.style.right = '0.625rem';
archiveMainRight.style.top = '0.5rem';
archiveMainRight.style.background = '#fffa';
archiveMainRight.style.backdropFilter = 'blur(0.2rem)';
archiveMainRight.style.webkitBackdropFilter = 'blur(0.2rem)';
archiveMainRight.style.borderRadius = '0.25rem';
archiveMainRight.style.boxShadow = '#ccc 0 0 0rem 0.0625rem, #0c0c0db3 0rem 0.5rem 1rem -0.25rem';
viewerHeader.style.borderRadius = '0.25rem 0.25rem 0 0';
} else {
listHeader.style.display = 'flex';
listBody.style.height = 'calc(100% - 2.25rem)';
listBody.style.overflowY = 'scroll';
listBodyItemWrap.style.display = 'flex';
if (mapContainer) mapContainer.style.display = 'none';
archiveMainRight.style.minWidth = '41rem';
archiveMainRight.style.maxWidth = '41rem';
archiveMainRight.style.height = '100%';
archiveMainRight.style.position = 'relative';
archiveMainRight.style.right = 'unset';
archiveMainRight.style.top = 'unset';
archiveMainRight.style.background = '#fff';
archiveMainRight.style.backdropFilter = 'none';
archiveMainRight.style.webkitBackdropFilter = 'none';
archiveMainRight.style.borderRadius = 'unset';
archiveMainRight.style.boxShadow = 'none';
viewerHeader.style.borderRadius = 'unset';
}
}
export function syncGroupStyle() {
let listContainer = document.querySelector('.archive-main .archive-main-center .list-container');
let isRecycleBinModal = document.querySelector('.recycle-bin-modal').style.display == 'flex';
if (isRecycleBinModal) listContainer = document.querySelector('.recycle-bin-modal .recycle-bin-wrap .list-container');
listContainer.querySelectorAll('.main-list-item').forEach(item => {
if (listContainer.querySelectorAll(`.list-item.selected[data-main-file-name="${item.dataset.mainFileName}"]`).length > 0) {
listContainer.querySelectorAll(`.list-item[data-main-file-name="${item.dataset.mainFileName}"]`).forEach(item => {
item.classList.add('group-style');
item.classList.remove('non-selected');
})
} else {
listContainer.querySelectorAll(`.list-item[data-main-file-name="${item.dataset.mainFileName}"]`).forEach(item => {
item.classList.remove('group-style');
})
}
})
}