reg.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * 验证电子邮箱格式
  3. */
  4. function email(value) {
  5. return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
  6. }
  7. /**
  8. * 验证手机格式
  9. */
  10. function mobile(value) {
  11. return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
  12. }
  13. /**
  14. * 验证URL格式
  15. */
  16. function url(value) {
  17. return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
  18. .test(value)
  19. }
  20. /**
  21. * 验证日期格式
  22. */
  23. function date(value) {
  24. if (!value) return false
  25. // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
  26. if (number(value)) value = +value
  27. return !/Invalid|NaN/.test(new Date(value).toString())
  28. }
  29. /**
  30. * 验证ISO类型的日期格式
  31. */
  32. function dateISO(value) {
  33. return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
  34. }
  35. /**
  36. * 验证十进制数字
  37. */
  38. function number(value) {
  39. return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
  40. }
  41. /**
  42. * 验证字符串
  43. */
  44. function string(value) {
  45. return typeof value === 'string'
  46. }
  47. /**
  48. * 验证整数
  49. */
  50. function digits(value) {
  51. return /^\d+$/.test(value)
  52. }
  53. /**
  54. * 验证身份证号码
  55. */
  56. function idCard(value) {
  57. return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
  58. value
  59. )
  60. }
  61. /**
  62. * 是否车牌号
  63. */
  64. function carNo(value) {
  65. value = value.trim();
  66. // 新能源车牌
  67. const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([A-HJ-K][A-HJ-NP-Z0-9][0-9]{4}$))/;
  68. // 旧车牌
  69. const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/;
  70. if (value.length === 7) {
  71. return creg.test(value)
  72. } if (value.length === 8) {
  73. return xreg.test(value)
  74. }
  75. return false
  76. }
  77. /**
  78. * 金额,只允许2位小数
  79. */
  80. function amount(value) {
  81. // 金额,只允许保留两位小数
  82. return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
  83. }
  84. /**
  85. * 中文
  86. */
  87. function chinese(value) {
  88. const reg = /^[\u4e00-\u9fa5]+$/gi
  89. return reg.test(value)
  90. }
  91. /**
  92. * 只能输入字母
  93. */
  94. function letter(value) {
  95. return /^[a-zA-Z]*$/.test(value)
  96. }
  97. /**
  98. * 只能是字母或者数字
  99. */
  100. function enOrNum(value) {
  101. // 英文或者数字
  102. const reg = /^[0-9a-zA-Z]*$/g
  103. return reg.test(value)
  104. }
  105. /**
  106. * 验证是否包含某个值
  107. */
  108. function contains(value, param) {
  109. return value.indexOf(param) >= 0
  110. }
  111. /**
  112. * 验证一个值范围[min, max]
  113. */
  114. function range(value, param) {
  115. return value >= param[0] && value <= param[1]
  116. }
  117. /**
  118. * 验证一个长度范围[min, max]
  119. */
  120. function rangeLength(value, param) {
  121. return value.length >= param[0] && value.length <= param[1]
  122. }
  123. /**
  124. * 是否固定电话
  125. */
  126. function landline(value) {
  127. const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
  128. return reg.test(value)
  129. }
  130. /**
  131. * 判断是否为空
  132. */
  133. function empty(value) {
  134. switch (typeof value) {
  135. case 'undefined':
  136. return true
  137. case 'string':
  138. if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
  139. break
  140. case 'boolean':
  141. if (!value) return true
  142. break
  143. case 'number':
  144. if (value === 0 || isNaN(value)) return true
  145. break
  146. case 'object':
  147. if (value === null || value.length === 0) return true
  148. for (const i in value) {
  149. return false
  150. }
  151. return true
  152. }
  153. return false
  154. }
  155. /**
  156. * 是否json字符串
  157. */
  158. function jsonString(value) {
  159. if (typeof value === 'string') {
  160. try {
  161. const obj = JSON.parse(value)
  162. if (typeof obj === 'object' && obj) {
  163. return true
  164. }
  165. return false
  166. } catch (e) {
  167. return false
  168. }
  169. }
  170. return false
  171. }
  172. /**
  173. * 是否数组
  174. */
  175. function array(value) {
  176. if (typeof Array.isArray === 'function') {
  177. return Array.isArray(value)
  178. }
  179. return Object.prototype.toString.call(value) === '[object Array]'
  180. }
  181. /**
  182. * 是否对象
  183. */
  184. function object(value) {
  185. return Object.prototype.toString.call(value) === '[object Object]'
  186. }
  187. /**
  188. * 是否短信验证码
  189. */
  190. function code(value, len = 6) {
  191. return new RegExp(`^\\d{${len}}$`).test(value)
  192. }
  193. /**
  194. * 是否函数方法
  195. * @param {Object} value
  196. */
  197. function func(value) {
  198. return typeof value === 'function'
  199. }
  200. /**
  201. * 是否promise对象
  202. * @param {Object} value
  203. */
  204. function promise(value) {
  205. return object(value) && func(value.then) && func(value.catch)
  206. }
  207. /** 是否图片格式
  208. * @param {Object} value
  209. */
  210. function image(value) {
  211. const newValue = value.split('?')[0]
  212. const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
  213. return IMAGE_REGEXP.test(newValue)
  214. }
  215. /**
  216. * 是否视频格式
  217. * @param {Object} value
  218. */
  219. function video(value) {
  220. const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
  221. return VIDEO_REGEXP.test(value)
  222. }
  223. /**
  224. * 是否为正则对象
  225. * @param {Object}
  226. * @return {Boolean}
  227. */
  228. function regExp(o) {
  229. return o && Object.prototype.toString.call(o) === '[object RegExp]'
  230. }
  231. /**
  232. * 通用脱敏函数
  233. * @param {string} content - 需要脱敏的内容(邮箱/手机号/姓名)
  234. * @param {number} [type=1] - 脱敏类型:1-邮箱(默认),2-手机,3-姓名
  235. * @returns {string} 脱敏后的内容,不符合规则返回原内容
  236. */
  237. function desensitizeContent(content, type = 1) {
  238. // 基础校验:内容为空或非字符串直接返回原内容
  239. if (!content || typeof content !== 'string') {
  240. return content;
  241. }
  242. // 去除首尾空格
  243. const trimContent = content.trim();
  244. switch (type) {
  245. // 1 - 邮箱脱敏
  246. case 1: {
  247. // 邮箱基本校验:包含@,且@前后有内容,总长度至少5位(如a@b.c)
  248. const emailReg = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
  249. if (!emailReg.test(trimContent) || trimContent.length < 5) {
  250. return content; // 不符合邮箱格式返回原内容
  251. }
  252. // 拆分邮箱:用户名@域名
  253. const [username, domain] = trimContent.split('@');
  254. // 用户名保留前2位,不足2位则保留1位,其余用*代替
  255. const safeUsername = username.length > 2
  256. ? username.substring(0, 2) + '*'.repeat(username.length - 2)
  257. : username.substring(0, 1) + '*'.repeat(username.length - 1);
  258. return `${safeUsername}@${domain}`;
  259. }
  260. // 2 - 手机号脱敏
  261. case 2: {
  262. // 手机号基本校验:11位数字,以1开头
  263. const phoneReg = /^1\d{10}$/;
  264. if (!phoneReg.test(trimContent) || trimContent.length !== 11) {
  265. return content; // 不符合手机号格式返回原内容
  266. }
  267. // 保留前3位和后4位,中间4位用*代替
  268. return trimContent.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
  269. }
  270. // 3 - 姓名脱敏
  271. case 3: {
  272. const nameLength = trimContent.length;
  273. // 姓名长度校验:至少1位,最多6位(常规姓名长度)
  274. if (nameLength < 1 || nameLength > 6) {
  275. return content;
  276. }
  277. // 单字姓名:直接返回
  278. if (nameLength === 1) {
  279. return trimContent;
  280. }
  281. // 双字姓名:保留首字,第二个字用*代替(如:李*)
  282. if (nameLength === 2) {
  283. return trimContent.substring(0, 1) + '*';
  284. }
  285. // 三字及以上:保留首尾字,中间用*代替(如:张*三、王**明)
  286. return trimContent.substring(0, 1) + '*'.repeat(nameLength - 2) + trimContent.substring(nameLength - 1);
  287. }
  288. // 未知类型:返回原内容
  289. default:
  290. return content;
  291. }
  292. }
  293. export default {
  294. email,
  295. mobile,
  296. url,
  297. date,
  298. dateISO,
  299. number,
  300. digits,
  301. idCard,
  302. carNo,
  303. amount,
  304. chinese,
  305. letter,
  306. enOrNum,
  307. contains,
  308. range,
  309. rangeLength,
  310. empty,
  311. isEmpty: empty,
  312. jsonString,
  313. landline,
  314. object,
  315. array,
  316. code,
  317. func,
  318. promise,
  319. video,
  320. image,
  321. regExp,
  322. string,
  323. desensitizeContent
  324. }