/************** * 필드 공통 유효성 검사 * watch, focus * form 필드는 반응형데이터 감지를 위해 ref 데이터 그대로 보내야한다 **************/ export function useWatchFocusValidate(form, pageId) { const errMsgObj = ref({}) // 에러메시지 객체 const ipv4Pattern = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; const ipv6Pattern = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$|^:(?::[0-9a-fA-F]{1,4}){1,7}$|^::$|^::(?:[0-9a-fA-F]{1,4}:){1,7}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}$|^(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}$|^(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}$|^:(?::[0-9a-fA-F]{1,4}){1,7}$|^::$|^::(?:[0-9a-fA-F]{1,4}:){1,7}$/; const portPattern = /^[1-9][0-9]{0,4}$/ const idPattern = /^[a-zA-Z][a-zA-Z0-9._-]{4,19}$/ let namePattern = /^[a-zA-Z가-힣]{2,10}$/ //const emailPattern = /^(?=.{1,40}$)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; // /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ const emailPattern = /^(?=.{1,40}$)[A-Za-z0-9]([-_.]?[A-Za-z0-9])*@[A-Za-z0-9]([-_.]?[A-Za-z0-9])*\.[A-Za-z]{2,3}$/; /** * 마지막 글자 받침체크 */ function isSingleCharacter(text){ var strGa = 44032 //가 var strHih = 55203 //힣 let lastStrCode = text.charCodeAt(text.length-1) if(lastStrCode < strGa || lastStrCode > strHih){ return false //한글이 아닌 경우 } return ((lastStrCode - strGa) % 28 == 0) } /** * 를/을 필터 * @param {*} text 필터 문자열 * @param {*} filter 필터 조사 neun : 는/은 leul :를/을 ro: 로/으로 */ function filterCheck(text, filter){ if(filter == '은' || filter == '는') return text + (isSingleCharacter(text) ? '는' : '은') if(filter == '을' || filter == '를') return text + (isSingleCharacter(text) ? '를' : '을') if(filter == '으로' || filter == '로') return text + (isSingleCharacter(text) ? '로' : '으로') if(filter == '이' || filter == '가') return text + (isSingleCharacter(text) ? '가' : '이') if(filter == '과' || filter == '와') return text + (isSingleCharacter(text) ? '와' : '과') } /** * @param {*} str 원본 문자열 * @param {*} target 문자열 교체 대상 * @param {*} filter 필터 조사 neun : 는/은 leul :를/을 ro: 로/으로 * @returns */ function getChangedStr(str, target){ if(!useUtil.isNull(str)){ let result = '' if(str.includes(target)){ let targetStr = str.substr(0, target.length+1) //조사를 변경하기 위해 교체대상의 다음문자까지 가져오기. let target2Str = str.substr(0, target.length+2) let lastStr = targetStr.substr(-1) if(target2Str.substr(-2) === '으로'){ lastStr = '으로' result = str.replace(target2Str, filterCheck(target, lastStr)) }else{ result = str.replace(targetStr, filterCheck(target, lastStr)) } }else{ result = str } return result } } /** * 에러메시지 리턴 * @param {*} key 필드 키 * @param {*} fieldName 필드 명 * @param {*} regex 필드 정규식 * @param {boolean} isRequire 필드 필수여부 * @param {boolean} requiredUpdate 필드 필수 상태 업데이트 여부 * @param {Object} params 나머지 항목 * @returns */ function fnErrorHandler(key, fieldName, regex=null, {...params}) { const value = form.value[key] // 필수 필드 항목 변경 시 빈값인 경우 초기 메시지 노출x if (params.requiredUpdate && useUtil.isNull(value)){ errMsgObj.value[key] = [] return; } // 현재 필드 필수 && 빈 값 if(params.fieldType === 'input') { if (params.isRequired && useUtil.isNull(value)) { errMsgObj.value[key] = [`${getChangedStr(fieldName + '을', fieldName)} 입력하세요.`]; return; } }else if(params.fieldType === 'select') { if (params.isRequired && useUtil.isNull(value)) { errMsgObj.value[key] = [`${getChangedStr(fieldName + '을', fieldName)} 선택하세요.`]; return; } } // 입력값이 있고 // 정규식을 사용하는 경우 if (!useUtil.isNull(value) && regex && regex.length > 0) { let isValid = null if(key === 'accountName') { const koreanRegex = /^[\uAC00-\uD7A3]+$/ const englishRegex = /^[A-Za-z,\.\-'\s]+$/ if (koreanRegex.test(value)) { regex[0] = /^[가-힣]{2,4}$/ isValid = regex.some(pattern => pattern.test(value)) } else if (englishRegex.test(value)) { regex[0] = /^[A-Za-z,\.\-'\s]{2,30}$/ isValid = regex.some(pattern => pattern.test(value)) } else { isValid = false } } else { isValid = regex.some(pattern => pattern.test(value)) } switch (key) { case 'ipAddrWeb': case 'ipAddrWeb': case 'udcIpAddrSubs': case 'statusIpAddr': case 'usmMcmIpAddr': case 'fmAuditIpAddr': errMsgObj.value[key] = isValid ? [] : [`IPv4 또는 IPv6 형식으로 입력하세요.`]; break; case 'portWeb': case 'udcPortSubs': case 'statusPort': case 'usmPsmPort': case 'usmMcmPort': case 'fmAuditPort': errMsgObj.value[key] = isValid && Number(value) >= 1 && Number(value) <= 65535 ? [] : [`1~65535 범위 내의 유효한 포트 번호를 입력하세요.`]; break; case 'accountId': errMsgObj.value[key] = isValid ? [] : [`영문, 숫자 5자리 ~ 20자리 입력하세요.`] break; case 'accountName': errMsgObj.value[key] = isValid ? [] : [`한글 입력 시 2~4자리 , 영문 입력 시 띄어쓰기&특문 , . - ' 포함 2자리 ~ 30자리 입력하세요.`] break; case 'email': errMsgObj.value[key] = isValid ? [] : [`한글, 영문, 특수문자, 숫자, 공백 1자리 ~ 40자리 입력하세요.`] break; default: errMsgObj.value[key] = isValid ? [] : [`${getChangedStr(fieldName + '을', fieldName)} 올바른 형식으로 입력하세요.`]; break; } } else { errMsgObj.value[key] = []; } } let fields = ref([]) switch (pageId) { case 'tenantMgmt': fields.value = [ { key: 'tenantName', name: '테넌트 이름', fieldType: 'input', isRequired: true}, { key: 'corpNum', name: '사업자번호', fieldType: 'input', isRequired: true}, { key: 'customerType', name: '고객 유형', fieldType: 'select', isRequired: true}, { key: 'imsiPrefix', name: 'IMSI Prefix', fieldType: 'input', isRequired: true}, { key: 'tenantCode', name: '테넌트 고유번호', fieldType: 'input', isRequired: true}, { key: 'tenantAddress', name: '테넌트 주소', fieldType: 'input', isRequired: true}, ] break;w case 'equipMgmt': fields.value = [ // 시스템 기본 정보 { key: 'emsName', name: '수집 시스템', fieldType: 'input', isRequired: true}, { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true}, { key: 'systemType', name: '시스템 유형', fieldType: 'select', isRequired: true}, { key: 'ipAddrWeb', name: 'WEB 접속 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: true}, { key: 'portWeb', name: 'WEB 접속 Port', regex: [portPattern], fieldType: 'input', isRequired: true}, // 연동 설정 정보 { key: 'udcIpAddrSubs', name: '가입자 관리 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false }, { key: 'udcPortSubs', name: '가입자 관리 Port', regex: [portPattern], fieldType: 'input', isRequired: false }, { key: 'usmPsmIpAddr', name: '통계 수집 IP (PSM)', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false }, { key: 'usmMcmIpAddr', name: '형상정보 수집 IP (MCM)', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false }, { key: 'usmPsmPort', name: '통계 수집 Port (PSM)', regex: [portPattern], fieldType: 'input', isRequired: false }, { key: 'usmMcmPort', name: '형상정보 수집 Port (MCM)', regex: [portPattern], fieldType: 'input', isRequired: false }, { key: 'statusIpAddr', name: '연결 확인 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false}, { key: 'statusPort', name: '연결 확인 Port', regex: [portPattern], fieldType: 'input', isRequired: false}, { key: 'usmFtpId', name: 'FTP ID', fieldType: 'input', isRequired: false}, { key: 'usmFtpPassword', name: 'FTP PASSWORD', fieldType: 'input', isRequired: false}, // 이벤트 AUDIT 연동 정보 { key: 'fmAuditIpAddr', name: 'Audit IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false }, { key: 'fmAuditPort', name: 'Audit Port', regex: [portPattern], fieldType: 'input', isRequired: false }, { key: 'fmAuditId', name: 'AUDIT ID', fieldType: 'input', isRequired: false}, { key: 'fmAuditPassword', name: 'AUDIT 비밀번호', fieldType: 'input', isRequired: false}, // 이벤트 TRAP 연동 정보 { key: 'trapVersion', name: 'TRAP 버전', fieldType: 'input', isRequired: true}, { key: 'trapV2CommunityName', name: 'TRAP V2 Community', fieldType: 'input', isRequired: true}, { key: 'trapV3SecurityName', name: 'TRAP V3 Security 이름', fieldType: 'input', isRequired: true}, { key: 'trapV3SecurityLevel', name: 'TRAP V3 Security 레벨', fieldType: 'input', isRequired: true}, { key: 'trapV3AuthProtocol', name: 'TRAP V3 인증 프로토콜', fieldType: 'input', isRequired: true}, { key: 'trapV3AuthPassword', name: 'TRAP V3 인증 비밀번호', fieldType: 'input', isRequired: true}, { key: 'trapV3PrivProtocol', name: 'TRAP V3 암호화 프로토콜', fieldType: 'input', isRequired: true}, { key: 'trapV3PrivPassword', name: 'TRAP V3 암호화 비밀번호', fieldType: 'input', isRequired: true} ] break; case 'neMgmt': fields.value = [ { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true}, { key: 'neGroup', name: 'NE 그룹 이름', fieldType: 'select', isRequired: true}, { key: 'neType', name: 'NE 유형', fieldType: 'select', isRequired: true}, { key: 'neName', name: 'NE 이름', fieldType: 'input', isRequired: true}, { key: 'emsName', name: '수집 시스템', fieldType: 'select', isRequired: true}, { key: 'neAddress', name: '위치 정보', fieldType: 'input', isRequired: true}, { key: 'neLocLatitude', name: '위도 값', fieldType: 'input', isRequired: true}, { key: 'neLocLongitude', name: '경도 값', fieldType: 'input', isRequired: true}, ] break; case 'neGroupMgmt': fields.value = [ { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true}, { key: 'neGroup', name: 'NE 그룹 이름', fieldType: 'input', isRequired: true}, { key: 'neGroupAddress', name: '위치 정보', fieldType: 'input', isRequired: true}, { key: 'neGroupLocLatitude', name: '위도 값', fieldType: 'input', isRequired: true}, { key: 'neGroupLocLongitude', name: '경도 값', fieldType: 'input', isRequired: true}, ] break; case 'userMgmt': fields.value = [ { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true}, { key: 'imsi2', name: 'IMSI', fieldType: 'input', isRequired: true}, { key: 'msisdns', name: 'MSISDN', fieldType: 'input', isRequired: true}, { key: 'skey', name: 'SKEY', fieldType: 'input', isRequired: true}, { key: 'opc', name: 'OPC', fieldType: 'input', isRequired: true}, { key: 'uplink', name: 'UE AMBR Uplink', fieldType: 'input', isRequired: true}, { key: 'downlink', name: 'UE AMBR Downlink', fieldType: 'input', isRequired: true}, { key: 'singleNssais', name: 'Single Nssai List', fieldType: 'input', isRequired: true}, { key: 'defaultNssais', name: 'Default Nssai List', fieldType: 'input', isRequired: true}, ] break; case 'accountMgmt': fields.value = [ { key: 'accountId', name: '계정ID', regex: [idPattern], fieldType: 'input', isRequired: true}, { key: 'accountName', name: '계정이름', regex: [namePattern], fieldType: 'input', isRequired: true}, { key: 'email', name: '이메일 주소', regex: [emailPattern], fieldType: 'input', isRequired: true}, { key: 'phoneNumber', name: '휴대폰번호', fieldType: 'input', isRequired: true}, ] break; case 'termsMgmt': fields.value = [] break; case 'connectSetMgmtTab4': fields.value = [ { key: 'ipAddr', name: 'IP', regex: [ipv4Pattern], fieldType: 'input', isRequired: true} ] break; default: fields.value = [] break; } fields.value.forEach((item) => { watch(() => form.value[item.key], () => { fnErrorHandler(item.key, item.name, item.regex, {isRequired: item.isRequired, fieldType: item.fieldType}) }) }) // 필수항목 변경 사항 있을 때 업데이트 function fnDataUpdate(requireFields){ fields.value.forEach((item) => { item.isRequired = requireFields.includes(item.key) // 모든 항목 재검사 fnErrorHandler(item.key, item.name, item.regex, { isRequired: item.isRequire, requiredUpdate:true, fieldType: item.fieldType}) watch(() => form.value[item.key], () => { fnErrorHandler(item.key, item.name, item.regex, {isRequired: item.isRequired, fieldType: item.fieldType}) }) }) } /** * 포커스 시 유효성 검사 * @param {*} key 필드 키 * @param {*} fieldName 필드이름 * @param {*} isRequired 필드필수여부 */ function fnFocusValidateField(key, fieldName, {...params}) { let ipKeys = ['ipAddrWeb', 'udcIpAddrSubs', 'usmPsmIpAddr', 'usmMcmIpAddr', 'statusIpAddr', 'ipAddr', 'fmAuditIpAddr'] let portKeys = ['portWeb', 'udcPortSubs', 'statusPort', 'usmMcmPort', 'usmPsmPort', 'fmAuditPort'] let idKeys = ['accountId'] let nameKeys = ['accountName'] let regex = [] if(ipKeys.includes(key)) regex = [ipv4Pattern, ipv6Pattern] else if(portKeys.includes(key)) regex = [portPattern] else if(idKeys.includes(key)) regex = [idPattern] else if(nameKeys.includes(key)) regex = [namePattern] else if(key == 'email') regex = [emailPattern] fnErrorHandler(key, fieldName, regex, {...params}) } return {errMsgObj, fnFocusValidateField, fnDataUpdate} }