useWatchFocusValidate.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /**************
  2. * 필드 공통 유효성 검사
  3. * watch, focus
  4. * form 필드는 반응형데이터 감지를 위해 ref 데이터 그대로 보내야한다
  5. **************/
  6. export function useWatchFocusValidate(form, pageId) {
  7. const errMsgObj = ref({}) // 에러메시지 객체
  8. 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]?)$/;
  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}$/;
  10. const portPattern = /^[1-9][0-9]{0,4}$/
  11. const idPattern = /^[a-zA-Z][a-zA-Z0-9._-]{4,19}$/
  12. let namePattern = /^[a-zA-Z가-힣]{2,10}$/
  13. //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,}$/
  14. 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}$/;
  15. /**
  16. * 마지막 글자 받침체크
  17. */
  18. function isSingleCharacter(text){
  19. var strGa = 44032 //가
  20. var strHih = 55203 //힣
  21. let lastStrCode = text.charCodeAt(text.length-1)
  22. if(lastStrCode < strGa || lastStrCode > strHih){
  23. return false //한글이 아닌 경우
  24. }
  25. return ((lastStrCode - strGa) % 28 == 0)
  26. }
  27. /**
  28. * 를/을 필터
  29. * @param {*} text 필터 문자열
  30. * @param {*} filter 필터 조사 neun : 는/은 leul :를/을 ro: 로/으로
  31. */
  32. function filterCheck(text, filter){
  33. if(filter == '은' || filter == '는') return text + (isSingleCharacter(text) ? '는' : '은')
  34. if(filter == '을' || filter == '를') return text + (isSingleCharacter(text) ? '를' : '을')
  35. if(filter == '으로' || filter == '로') return text + (isSingleCharacter(text) ? '로' : '으로')
  36. if(filter == '이' || filter == '가') return text + (isSingleCharacter(text) ? '가' : '이')
  37. if(filter == '과' || filter == '와') return text + (isSingleCharacter(text) ? '와' : '과')
  38. }
  39. /**
  40. * @param {*} str 원본 문자열
  41. * @param {*} target 문자열 교체 대상
  42. * @param {*} filter 필터 조사 neun : 는/은 leul :를/을 ro: 로/으로
  43. * @returns
  44. */
  45. function getChangedStr(str, target){
  46. if(!useUtil.isNull(str)){
  47. let result = ''
  48. if(str.includes(target)){
  49. let targetStr = str.substr(0, target.length+1) //조사를 변경하기 위해 교체대상의 다음문자까지 가져오기.
  50. let target2Str = str.substr(0, target.length+2)
  51. let lastStr = targetStr.substr(-1)
  52. if(target2Str.substr(-2) === '으로'){
  53. lastStr = '으로'
  54. result = str.replace(target2Str, filterCheck(target, lastStr))
  55. }else{
  56. result = str.replace(targetStr, filterCheck(target, lastStr))
  57. }
  58. }else{
  59. result = str
  60. }
  61. return result
  62. }
  63. }
  64. /**
  65. * 에러메시지 리턴
  66. * @param {*} key 필드 키
  67. * @param {*} fieldName 필드 명
  68. * @param {*} regex 필드 정규식
  69. * @param {boolean} isRequire 필드 필수여부
  70. * @param {boolean} requiredUpdate 필드 필수 상태 업데이트 여부
  71. * @param {Object} params 나머지 항목
  72. * @returns
  73. */
  74. function fnErrorHandler(key, fieldName, regex=null, {...params}) {
  75. const value = form.value[key]
  76. // 필수 필드 항목 변경 시 빈값인 경우 초기 메시지 노출x
  77. if (params.requiredUpdate && useUtil.isNull(value)){
  78. errMsgObj.value[key] = []
  79. return;
  80. }
  81. // 현재 필드 필수 && 빈 값
  82. if(params.fieldType === 'input') {
  83. if (params.isRequired && useUtil.isNull(value)) {
  84. errMsgObj.value[key] = [`${getChangedStr(fieldName + '을', fieldName)} 입력하세요.`];
  85. return;
  86. }
  87. }else if(params.fieldType === 'select') {
  88. if (params.isRequired && useUtil.isNull(value)) {
  89. errMsgObj.value[key] = [`${getChangedStr(fieldName + '을', fieldName)} 선택하세요.`];
  90. return;
  91. }
  92. }
  93. // 입력값이 있고
  94. // 정규식을 사용하는 경우
  95. if (!useUtil.isNull(value) && regex && regex.length > 0) {
  96. let isValid = null
  97. if(key === 'accountName') {
  98. const koreanRegex = /^[\uAC00-\uD7A3]+$/
  99. const englishRegex = /^[A-Za-z,\.\-'\s]+$/
  100. if (koreanRegex.test(value)) {
  101. regex[0] = /^[가-힣]{2,4}$/
  102. isValid = regex.some(pattern => pattern.test(value))
  103. } else if (englishRegex.test(value)) {
  104. regex[0] = /^[A-Za-z,\.\-'\s]{2,30}$/
  105. isValid = regex.some(pattern => pattern.test(value))
  106. } else {
  107. isValid = false
  108. }
  109. } else {
  110. isValid = regex.some(pattern => pattern.test(value))
  111. }
  112. switch (key) {
  113. case 'ipAddrWeb':
  114. case 'ipAddrWeb':
  115. case 'udcIpAddrSubs':
  116. case 'statusIpAddr':
  117. case 'usmMcmIpAddr':
  118. case 'fmAuditIpAddr':
  119. errMsgObj.value[key] = isValid ? [] : [`IPv4 또는 IPv6 형식으로 입력하세요.`];
  120. break;
  121. case 'portWeb':
  122. case 'udcPortSubs':
  123. case 'statusPort':
  124. case 'usmPsmPort':
  125. case 'usmMcmPort':
  126. case 'fmAuditPort':
  127. errMsgObj.value[key] = isValid && Number(value) >= 1 && Number(value) <= 65535 ? [] : [`1~65535 범위 내의 유효한 포트 번호를 입력하세요.`];
  128. break;
  129. case 'accountId':
  130. errMsgObj.value[key] = isValid ? [] : [`영문, 숫자 5자리 ~ 20자리 입력하세요.`]
  131. break;
  132. case 'accountName':
  133. errMsgObj.value[key] = isValid ? [] : [`한글 입력 시 2~4자리 , 영문 입력 시 띄어쓰기&특문 , . - ' 포함 2자리 ~ 30자리 입력하세요.`]
  134. break;
  135. case 'email':
  136. errMsgObj.value[key] = isValid ? [] : [`한글, 영문, 특수문자, 숫자, 공백 1자리 ~ 40자리 입력하세요.`]
  137. break;
  138. default:
  139. errMsgObj.value[key] = isValid ? [] : [`${getChangedStr(fieldName + '을', fieldName)} 올바른 형식으로 입력하세요.`];
  140. break;
  141. }
  142. } else {
  143. errMsgObj.value[key] = [];
  144. }
  145. }
  146. let fields = ref([])
  147. switch (pageId) {
  148. case 'tenantMgmt':
  149. fields.value = [
  150. { key: 'tenantName', name: '테넌트 이름', fieldType: 'input', isRequired: true},
  151. { key: 'corpNum', name: '사업자번호', fieldType: 'input', isRequired: true},
  152. { key: 'customerType', name: '고객 유형', fieldType: 'select', isRequired: true},
  153. { key: 'imsiPrefix', name: 'IMSI Prefix', fieldType: 'input', isRequired: true},
  154. { key: 'tenantCode', name: '테넌트 고유번호', fieldType: 'input', isRequired: true},
  155. { key: 'tenantAddress', name: '테넌트 주소', fieldType: 'input', isRequired: true},
  156. ]
  157. break;w
  158. case 'equipMgmt':
  159. fields.value = [
  160. // 시스템 기본 정보
  161. { key: 'emsName', name: '수집 시스템', fieldType: 'input', isRequired: true},
  162. { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true},
  163. { key: 'systemType', name: '시스템 유형', fieldType: 'select', isRequired: true},
  164. { key: 'ipAddrWeb', name: 'WEB 접속 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: true},
  165. { key: 'portWeb', name: 'WEB 접속 Port', regex: [portPattern], fieldType: 'input', isRequired: true},
  166. // 연동 설정 정보
  167. { key: 'udcIpAddrSubs', name: '가입자 관리 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false },
  168. { key: 'udcPortSubs', name: '가입자 관리 Port', regex: [portPattern], fieldType: 'input', isRequired: false },
  169. { key: 'usmPsmIpAddr', name: '통계 수집 IP (PSM)', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false },
  170. { key: 'usmMcmIpAddr', name: '형상정보 수집 IP (MCM)', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false },
  171. { key: 'usmPsmPort', name: '통계 수집 Port (PSM)', regex: [portPattern], fieldType: 'input', isRequired: false },
  172. { key: 'usmMcmPort', name: '형상정보 수집 Port (MCM)', regex: [portPattern], fieldType: 'input', isRequired: false },
  173. { key: 'statusIpAddr', name: '연결 확인 IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false},
  174. { key: 'statusPort', name: '연결 확인 Port', regex: [portPattern], fieldType: 'input', isRequired: false},
  175. { key: 'usmFtpId', name: 'FTP ID', fieldType: 'input', isRequired: false},
  176. { key: 'usmFtpPassword', name: 'FTP PASSWORD', fieldType: 'input', isRequired: false},
  177. // 이벤트 AUDIT 연동 정보
  178. { key: 'fmAuditIpAddr', name: 'Audit IP', regex: [ipv4Pattern, ipv6Pattern], fieldType: 'input', isRequired: false },
  179. { key: 'fmAuditPort', name: 'Audit Port', regex: [portPattern], fieldType: 'input', isRequired: false },
  180. { key: 'fmAuditId', name: 'AUDIT ID', fieldType: 'input', isRequired: false},
  181. { key: 'fmAuditPassword', name: 'AUDIT 비밀번호', fieldType: 'input', isRequired: false},
  182. // 이벤트 TRAP 연동 정보
  183. { key: 'trapVersion', name: 'TRAP 버전', fieldType: 'input', isRequired: true},
  184. { key: 'trapV2CommunityName', name: 'TRAP V2 Community', fieldType: 'input', isRequired: true},
  185. { key: 'trapV3SecurityName', name: 'TRAP V3 Security 이름', fieldType: 'input', isRequired: true},
  186. { key: 'trapV3SecurityLevel', name: 'TRAP V3 Security 레벨', fieldType: 'input', isRequired: true},
  187. { key: 'trapV3AuthProtocol', name: 'TRAP V3 인증 프로토콜', fieldType: 'input', isRequired: true},
  188. { key: 'trapV3AuthPassword', name: 'TRAP V3 인증 비밀번호', fieldType: 'input', isRequired: true},
  189. { key: 'trapV3PrivProtocol', name: 'TRAP V3 암호화 프로토콜', fieldType: 'input', isRequired: true},
  190. { key: 'trapV3PrivPassword', name: 'TRAP V3 암호화 비밀번호', fieldType: 'input', isRequired: true}
  191. ]
  192. break;
  193. case 'neMgmt':
  194. fields.value = [
  195. { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true},
  196. { key: 'neGroup', name: 'NE 그룹 이름', fieldType: 'select', isRequired: true},
  197. { key: 'neType', name: 'NE 유형', fieldType: 'select', isRequired: true},
  198. { key: 'neName', name: 'NE 이름', fieldType: 'input', isRequired: true},
  199. { key: 'emsName', name: '수집 시스템', fieldType: 'select', isRequired: true},
  200. { key: 'neAddress', name: '위치 정보', fieldType: 'input', isRequired: true},
  201. { key: 'neLocLatitude', name: '위도 값', fieldType: 'input', isRequired: true},
  202. { key: 'neLocLongitude', name: '경도 값', fieldType: 'input', isRequired: true},
  203. ]
  204. break;
  205. case 'neGroupMgmt':
  206. fields.value = [
  207. { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true},
  208. { key: 'neGroup', name: 'NE 그룹 이름', fieldType: 'input', isRequired: true},
  209. { key: 'neGroupAddress', name: '위치 정보', fieldType: 'input', isRequired: true},
  210. { key: 'neGroupLocLatitude', name: '위도 값', fieldType: 'input', isRequired: true},
  211. { key: 'neGroupLocLongitude', name: '경도 값', fieldType: 'input', isRequired: true},
  212. ]
  213. break;
  214. case 'userMgmt':
  215. fields.value = [
  216. { key: 'tenantName', name: '테넌트 이름', fieldType: 'select', isRequired: true},
  217. { key: 'imsi2', name: 'IMSI', fieldType: 'input', isRequired: true},
  218. { key: 'msisdns', name: 'MSISDN', fieldType: 'input', isRequired: true},
  219. { key: 'skey', name: 'SKEY', fieldType: 'input', isRequired: true},
  220. { key: 'opc', name: 'OPC', fieldType: 'input', isRequired: true},
  221. { key: 'uplink', name: 'UE AMBR Uplink', fieldType: 'input', isRequired: true},
  222. { key: 'downlink', name: 'UE AMBR Downlink', fieldType: 'input', isRequired: true},
  223. { key: 'singleNssais', name: 'Single Nssai List', fieldType: 'input', isRequired: true},
  224. { key: 'defaultNssais', name: 'Default Nssai List', fieldType: 'input', isRequired: true},
  225. ]
  226. break;
  227. case 'accountMgmt':
  228. fields.value = [
  229. { key: 'accountId', name: '계정ID', regex: [idPattern], fieldType: 'input', isRequired: true},
  230. { key: 'accountName', name: '계정이름', regex: [namePattern], fieldType: 'input', isRequired: true},
  231. { key: 'email', name: '이메일 주소', regex: [emailPattern], fieldType: 'input', isRequired: true},
  232. { key: 'phoneNumber', name: '휴대폰번호', fieldType: 'input', isRequired: true},
  233. ]
  234. break;
  235. case 'termsMgmt':
  236. fields.value = []
  237. break;
  238. case 'connectSetMgmtTab4':
  239. fields.value = [
  240. { key: 'ipAddr', name: 'IP', regex: [ipv4Pattern], fieldType: 'input', isRequired: true}
  241. ]
  242. break;
  243. default:
  244. fields.value = []
  245. break;
  246. }
  247. fields.value.forEach((item) => {
  248. watch(() => form.value[item.key], () => {
  249. fnErrorHandler(item.key, item.name, item.regex, {isRequired: item.isRequired, fieldType: item.fieldType})
  250. })
  251. })
  252. // 필수항목 변경 사항 있을 때 업데이트
  253. function fnDataUpdate(requireFields){
  254. fields.value.forEach((item) => {
  255. item.isRequired = requireFields.includes(item.key)
  256. // 모든 항목 재검사
  257. fnErrorHandler(item.key, item.name, item.regex, { isRequired: item.isRequire, requiredUpdate:true, fieldType: item.fieldType})
  258. watch(() => form.value[item.key], () => {
  259. fnErrorHandler(item.key, item.name, item.regex, {isRequired: item.isRequired, fieldType: item.fieldType})
  260. })
  261. })
  262. }
  263. /**
  264. * 포커스 시 유효성 검사
  265. * @param {*} key 필드 키
  266. * @param {*} fieldName 필드이름
  267. * @param {*} isRequired 필드필수여부
  268. */
  269. function fnFocusValidateField(key, fieldName, {...params}) {
  270. let ipKeys = ['ipAddrWeb', 'udcIpAddrSubs', 'usmPsmIpAddr', 'usmMcmIpAddr', 'statusIpAddr', 'ipAddr', 'fmAuditIpAddr']
  271. let portKeys = ['portWeb', 'udcPortSubs', 'statusPort', 'usmMcmPort', 'usmPsmPort', 'fmAuditPort']
  272. let idKeys = ['accountId']
  273. let nameKeys = ['accountName']
  274. let regex = []
  275. if(ipKeys.includes(key)) regex = [ipv4Pattern, ipv6Pattern]
  276. else if(portKeys.includes(key)) regex = [portPattern]
  277. else if(idKeys.includes(key)) regex = [idPattern]
  278. else if(nameKeys.includes(key)) regex = [namePattern]
  279. else if(key == 'email') regex = [emailPattern]
  280. fnErrorHandler(key, fieldName, regex, {...params})
  281. }
  282. return {errMsgObj, fnFocusValidateField, fnDataUpdate}
  283. }