htc.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /**
  2. * @description 通用方法汇总
  3. */
  4. /**
  5. * @description 如果value小于min,取min;如果value大于max,取max
  6. * @param {number} min
  7. * @param {number} max
  8. * @param {number} value
  9. */
  10. function range(min = 0, max = 0, value = 0) {
  11. return Math.max(min, Math.min(max, Number(value)))
  12. }
  13. /**
  14. * @description 进行延时,以达到可以简写代码的目的 比如: await uni.$u.sleep(20)将会阻塞20ms
  15. * @param {number} value 堵塞时间 单位ms 毫秒
  16. * @returns {Promise} 返回promise
  17. */
  18. function sleep(value = 30) {
  19. return new Promise((resolve) => {
  20. setTimeout(() => {
  21. resolve()
  22. }, value)
  23. })
  24. }
  25. /**
  26. * @description 取一个区间数
  27. * @param {Number} min 最小值
  28. * @param {Number} max 最大值
  29. */
  30. function random(min, max) {
  31. if (min >= 0 && max > 0 && max >= min) {
  32. const gab = max - min + 1
  33. return Math.floor(Math.random() * gab + min)
  34. }
  35. return 0
  36. }
  37. /**
  38. * @param {Number} len uuid的长度
  39. * @param {Boolean} firstU 将返回的首字母置为"u"
  40. * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
  41. */
  42. function guid(len = 32, firstU = true, radix = null) {
  43. const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  44. const uuid = []
  45. radix = radix || chars.length
  46. if (len) {
  47. // 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
  48. for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
  49. } else {
  50. let r
  51. // rfc4122标准要求返回的uuid中,某些位为固定的字符
  52. uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
  53. uuid[14] = '4'
  54. for (let i = 0; i < 36; i++) {
  55. if (!uuid[i]) {
  56. r = 0 | Math.random() * 16
  57. uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
  58. }
  59. }
  60. }
  61. // 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
  62. if (firstU) {
  63. uuid.shift()
  64. return `u${uuid.join('')}`
  65. }
  66. return uuid.join('')
  67. }
  68. /**
  69. * @description 样式转换
  70. * 对象转字符串,或者字符串转对象
  71. * @param {object | string} customStyle 需要转换的目标
  72. * @param {String} target 转换的目的,object-转为对象,string-转为字符串
  73. * @returns {object|string}
  74. */
  75. function addStyle(customStyle, target = 'object') {
  76. // 字符串转字符串,对象转对象情形,直接返回
  77. if (test.empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
  78. typeof(customStyle) === 'string') {
  79. return customStyle
  80. }
  81. // 字符串转对象
  82. if (target === 'object') {
  83. // 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
  84. customStyle = trim(customStyle)
  85. // 根据";"将字符串转为数组形式
  86. const styleArray = customStyle.split(';')
  87. const style = {}
  88. // 历遍数组,拼接成对象
  89. for (let i = 0; i < styleArray.length; i++) {
  90. // 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
  91. if (styleArray[i]) {
  92. const item = styleArray[i].split(':')
  93. style[trim(item[0])] = trim(item[1])
  94. }
  95. }
  96. return style
  97. }
  98. // 这里为对象转字符串形式
  99. let string = ''
  100. for (const i in customStyle) {
  101. // 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
  102. const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
  103. string += `${key}:${customStyle[i]};`
  104. }
  105. // 去除两端空格
  106. return trim(string)
  107. }
  108. /**
  109. * @description 深度克隆
  110. * @param {object} obj 需要深度克隆的对象
  111. * @param cache 缓存
  112. * @returns {*} 克隆后的对象或者原值(不是对象)
  113. */
  114. function deepClone(obj, cache = new WeakMap()) {
  115. if (obj === null || typeof obj !== 'object') return obj;
  116. if (cache.has(obj)) return cache.get(obj);
  117. let clone;
  118. if (obj instanceof Date) {
  119. clone = new Date(obj.getTime());
  120. } else if (obj instanceof RegExp) {
  121. clone = new RegExp(obj);
  122. } else if (obj instanceof Map) {
  123. clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
  124. } else if (obj instanceof Set) {
  125. clone = new Set(Array.from(obj, value => deepClone(value, cache)));
  126. } else if (Array.isArray(obj)) {
  127. clone = obj.map(value => deepClone(value, cache));
  128. } else if (Object.prototype.toString.call(obj) === '[object Object]') {
  129. clone = Object.create(Object.getPrototypeOf(obj));
  130. cache.set(obj, clone);
  131. for (const [key, value] of Object.entries(obj)) {
  132. clone[key] = deepClone(value, cache);
  133. }
  134. } else {
  135. clone = Object.assign({}, obj);
  136. }
  137. cache.set(obj, clone);
  138. return clone;
  139. }
  140. /**
  141. * @description JS对象深度合并
  142. * @param {object} target 需要拷贝的对象
  143. * @param {object} source 拷贝的来源对象
  144. * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
  145. */
  146. function deepMerge(target = {}, source = {}) {
  147. target = deepClone(target)
  148. if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
  149. const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
  150. for (const prop in source) {
  151. if (!source.hasOwnProperty(prop)) continue;
  152. const sourceValue = source[prop];
  153. const targetValue = merged[prop];
  154. if (sourceValue instanceof Date) {
  155. merged[prop] = new Date(sourceValue);
  156. } else if (sourceValue instanceof RegExp) {
  157. merged[prop] = new RegExp(sourceValue);
  158. } else if (sourceValue instanceof Map) {
  159. merged[prop] = new Map(sourceValue);
  160. } else if (sourceValue instanceof Set) {
  161. merged[prop] = new Set(sourceValue);
  162. } else if (typeof sourceValue === 'object' && sourceValue !== null) {
  163. merged[prop] = deepMerge(targetValue, sourceValue);
  164. } else {
  165. merged[prop] = sourceValue;
  166. }
  167. }
  168. return merged;
  169. }
  170. /**
  171. * @description 打乱数组
  172. * @param {array} array 需要打乱的数组
  173. * @returns {array} 打乱后的数组
  174. */
  175. function randomArray(array = []) {
  176. // 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
  177. return array.sort(() => Math.random() - 0.5)
  178. }
  179. // padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
  180. // 所以这里做一个兼容polyfill的兼容处理
  181. if (!String.prototype.padStart) {
  182. // 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
  183. String.prototype.padStart = function(maxLength, fillString = ' ') {
  184. if (Object.prototype.toString.call(fillString) !== '[object String]') {
  185. throw new TypeError(
  186. 'fillString must be String'
  187. )
  188. }
  189. const str = this
  190. // 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
  191. if (str.length >= maxLength) return String(str)
  192. const fillLength = maxLength - str.length
  193. let times = Math.ceil(fillLength / fillString.length)
  194. while (times >>= 1) {
  195. fillString += fillString
  196. if (times === 1) {
  197. fillString += fillString
  198. }
  199. }
  200. return fillString.slice(0, fillLength) + str
  201. }
  202. }
  203. /**
  204. * @description 格式化时间
  205. * @param {String|Number} dateTime 需要格式化的时间戳
  206. * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
  207. * @returns {string} 返回格式化后的字符串
  208. */
  209. function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
  210. let date
  211. // 若传入时间为假值,则取当前时间
  212. if (!dateTime) {
  213. date = new Date()
  214. }
  215. // 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
  216. else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
  217. date = new Date(dateTime * 1000)
  218. }
  219. // 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
  220. else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
  221. date = new Date(Number(dateTime))
  222. }
  223. // 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
  224. // 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
  225. else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
  226. date = new Date(dateTime.replace(/-/g, '/'))
  227. }
  228. // 其他都认为符合 RFC 2822 规范
  229. else {
  230. date = new Date(dateTime)
  231. }
  232. const timeSource = {
  233. 'y': date.getFullYear().toString(), // 年
  234. 'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
  235. 'd': date.getDate().toString().padStart(2, '0'), // 日
  236. 'h': date.getHours().toString().padStart(2, '0'), // 时
  237. 'M': date.getMinutes().toString().padStart(2, '0'), // 分
  238. 's': date.getSeconds().toString().padStart(2, '0') // 秒
  239. // 有其他格式化字符需求可以继续添加,必须转化成字符串
  240. }
  241. for (const key in timeSource) {
  242. const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
  243. if (ret) {
  244. // 年可能只需展示两位
  245. const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
  246. formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
  247. }
  248. }
  249. return formatStr
  250. }
  251. /**
  252. * @description 时间戳转为多久之前
  253. * @param {String|Number} timestamp 时间戳
  254. * @param {String|Boolean} format
  255. * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
  256. * 如果为布尔值false,无论什么时间,都返回多久以前的格式
  257. * @returns {string} 转化后的内容
  258. */
  259. function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
  260. if (timestamp == null) timestamp = Number(new Date())
  261. timestamp = parseInt(timestamp)
  262. // 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
  263. if (timestamp.toString().length == 10) timestamp *= 1000
  264. let timer = (new Date()).getTime() - timestamp
  265. timer = parseInt(timer / 1000)
  266. // 如果小于5分钟,则返回"刚刚",其他以此类推
  267. let tips = ''
  268. switch (true) {
  269. case timer < 300:
  270. tips = '刚刚'
  271. break
  272. case timer >= 300 && timer < 3600:
  273. tips = `${parseInt(timer / 60)}分钟前`
  274. break
  275. case timer >= 3600 && timer < 86400:
  276. tips = `${parseInt(timer / 3600)}小时前`
  277. break
  278. case timer >= 86400 && timer < 2592000:
  279. tips = `${parseInt(timer / 86400)}天前`
  280. break
  281. default:
  282. // 如果format为false,则无论什么时间戳,都显示xx之前
  283. if (format === false) {
  284. if (timer >= 2592000 && timer < 365 * 86400) {
  285. tips = `${parseInt(timer / (86400 * 30))}个月前`
  286. } else {
  287. tips = `${parseInt(timer / (86400 * 365))}年前`
  288. }
  289. } else {
  290. tips = timeFormat(timestamp, format)
  291. }
  292. }
  293. return tips
  294. }
  295. /**
  296. * @description 去除空格
  297. * @param String str 需要去除空格的字符串
  298. * @param String pos both(左右)|left|right|all 默认both
  299. */
  300. function trim(str, pos = 'both') {
  301. str = String(str)
  302. if (pos == 'both') {
  303. return str.replace(/^\s+|\s+$/g, '')
  304. }
  305. if (pos == 'left') {
  306. return str.replace(/^\s*/, '')
  307. }
  308. if (pos == 'right') {
  309. return str.replace(/(\s*$)/g, '')
  310. }
  311. if (pos == 'all') {
  312. return str.replace(/\s+/g, '')
  313. }
  314. return str
  315. }
  316. /**
  317. * @description 对象转url参数
  318. * @param {object} data,对象
  319. * @param {Boolean} isPrefix,是否自动加上"?"
  320. * @param {string} arrayFormat 规则 indices|brackets|repeat|comma
  321. */
  322. function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
  323. const prefix = isPrefix ? '?' : ''
  324. const _result = []
  325. if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
  326. for (const key in data) {
  327. const value = data[key]
  328. // 去掉为空的参数
  329. if (['', undefined, null].indexOf(value) >= 0) {
  330. continue
  331. }
  332. // 如果值为数组,另行处理
  333. if (value.constructor === Array) {
  334. // e.g. {ids: [1, 2, 3]}
  335. switch (arrayFormat) {
  336. case 'indices':
  337. // 结果: ids[0]=1&ids[1]=2&ids[2]=3
  338. for (let i = 0; i < value.length; i++) {
  339. _result.push(`${key}[${i}]=${value[i]}`)
  340. }
  341. break
  342. case 'brackets':
  343. // 结果: ids[]=1&ids[]=2&ids[]=3
  344. value.forEach((_value) => {
  345. _result.push(`${key}[]=${_value}`)
  346. })
  347. break
  348. case 'repeat':
  349. // 结果: ids=1&ids=2&ids=3
  350. value.forEach((_value) => {
  351. _result.push(`${key}=${_value}`)
  352. })
  353. break
  354. case 'comma':
  355. // 结果: ids=1,2,3
  356. let commaStr = ''
  357. value.forEach((_value) => {
  358. commaStr += (commaStr ? ',' : '') + _value
  359. })
  360. _result.push(`${key}=${commaStr}`)
  361. break
  362. default:
  363. value.forEach((_value) => {
  364. _result.push(`${key}[]=${_value}`)
  365. })
  366. }
  367. } else {
  368. _result.push(`${key}=${value}`)
  369. }
  370. }
  371. return _result.length ? prefix + _result.join('&') : ''
  372. }
  373. /**
  374. * @description 日期的月或日补零操作
  375. * @param {String} value 需要补零的值
  376. */
  377. function padZero(value) {
  378. return `00${value}`.slice(-2)
  379. }
  380. /**
  381. * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
  382. * @param {object} obj 对象
  383. * @param {string} key 需要获取的属性字段
  384. * @returns {*}
  385. */
  386. function getProperty(obj, key) {
  387. if (!obj) {
  388. return
  389. }
  390. if (typeof key !== 'string' || key === '') {
  391. return ''
  392. }
  393. if (key.indexOf('.') !== -1) {
  394. const keys = key.split('.')
  395. let firstObj = obj[keys[0]] || {}
  396. for (let i = 1; i < keys.length; i++) {
  397. if (firstObj) {
  398. firstObj = firstObj[keys[i]]
  399. }
  400. }
  401. return firstObj
  402. }
  403. return obj[key]
  404. }
  405. /**
  406. * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
  407. * @param {object} obj 对象
  408. * @param {string} key 需要设置的属性
  409. * @param {string} value 设置的值
  410. */
  411. function setProperty(obj, key, value) {
  412. if (!obj) {
  413. return
  414. }
  415. // 递归赋值
  416. const inFn = function(_obj, keys, v) {
  417. // 最后一个属性key
  418. if (keys.length === 1) {
  419. _obj[keys[0]] = v
  420. return
  421. }
  422. // 0~length-1个key
  423. while (keys.length > 1) {
  424. const k = keys[0]
  425. if (!_obj[k] || (typeof _obj[k] !== 'object')) {
  426. _obj[k] = {}
  427. }
  428. const key = keys.shift()
  429. // 自调用判断是否存在属性,不存在则自动创建对象
  430. inFn(_obj[k], keys, v)
  431. }
  432. }
  433. if (typeof key !== 'string' || key === '') {
  434. } else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
  435. const keys = key.split('.')
  436. inFn(obj, keys, value)
  437. } else {
  438. obj[key] = value
  439. }
  440. }
  441. let timeout = null
  442. /**
  443. * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
  444. *
  445. * @param {Function} func 要执行的回调函数
  446. * @param {Number} wait 延时的时间
  447. * @param {Boolean} immediate 是否立即执行
  448. * @return null
  449. */
  450. function debounce(func, wait = 500, immediate = false) {
  451. // 清除定时器
  452. if (timeout !== null) clearTimeout(timeout)
  453. // 立即执行,此类情况一般用不到
  454. if (immediate) {
  455. const callNow = !timeout
  456. timeout = setTimeout(() => {
  457. timeout = null
  458. }, wait)
  459. if (callNow) typeof func === 'function' && func()
  460. } else {
  461. // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
  462. timeout = setTimeout(() => {
  463. typeof func === 'function' && func()
  464. }, wait)
  465. }
  466. }
  467. let timer;
  468. let flag;
  469. /**
  470. * 节流原理:在一定时间内,只能触发一次
  471. *
  472. * @param {Function} func 要执行的回调函数
  473. * @param {Number} wait 延时的时间
  474. * @param {Boolean} immediate 是否立即执行
  475. * @return null
  476. */
  477. function throttle(func, wait = 500, immediate = true) {
  478. if (immediate) {
  479. if (!flag) {
  480. flag = true
  481. // 如果是立即执行,则在wait毫秒内开始时执行
  482. typeof func === 'function' && func()
  483. timer = setTimeout(() => {
  484. flag = false
  485. }, wait)
  486. }
  487. } else if (!flag) {
  488. flag = true
  489. // 如果是非立即执行,则在wait毫秒内的结束处执行
  490. timer = setTimeout(() => {
  491. flag = false
  492. typeof func === 'function' && func()
  493. }, wait)
  494. }
  495. }
  496. //-------------------------------------- 验证部分
  497. /**
  498. * 验证电子邮箱格式
  499. */
  500. function email(value) {
  501. return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
  502. }
  503. /**
  504. * 验证手机格式
  505. */
  506. function mobile(value) {
  507. return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
  508. }
  509. /**
  510. * 验证URL格式
  511. */
  512. function url(value) {
  513. 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_!~*'().;?:@&=+$,%#-]+)+\/?)$/
  514. .test(value)
  515. }
  516. /**
  517. * 验证日期格式
  518. */
  519. function date(value) {
  520. if (!value) return false
  521. // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
  522. if (number(value)) value = +value
  523. return !/Invalid|NaN/.test(new Date(value).toString())
  524. }
  525. /**
  526. * 验证ISO类型的日期格式
  527. */
  528. function dateISO(value) {
  529. return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
  530. }
  531. /**
  532. * 验证十进制数字
  533. */
  534. function number(value) {
  535. return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
  536. }
  537. /**
  538. * 验证字符串
  539. */
  540. function string(value) {
  541. return typeof value === 'string'
  542. }
  543. /**
  544. * 验证整数
  545. */
  546. function digits(value) {
  547. return /^\d+$/.test(value)
  548. }
  549. /**
  550. * 验证身份证号码
  551. */
  552. function idCard(value) {
  553. 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(
  554. value
  555. )
  556. }
  557. /**
  558. * 是否车牌号
  559. */
  560. function carNo(value) {
  561. // 新能源车牌
  562. const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
  563. // 旧车牌
  564. const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
  565. if (value.length === 7) {
  566. return creg.test(value)
  567. } if (value.length === 8) {
  568. return xreg.test(value)
  569. }
  570. return false
  571. }
  572. /**
  573. * 金额,只允许2位小数
  574. */
  575. function amount(value) {
  576. // 金额,只允许保留两位小数
  577. return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
  578. }
  579. /**
  580. * 中文
  581. */
  582. function chinese(value) {
  583. const reg = /^[\u4e00-\u9fa5]+$/gi
  584. return reg.test(value)
  585. }
  586. /**
  587. * 只能输入字母
  588. */
  589. function letter(value) {
  590. return /^[a-zA-Z]*$/.test(value)
  591. }
  592. /**
  593. * 只能是字母或者数字
  594. */
  595. function enOrNum(value) {
  596. // 英文或者数字
  597. const reg = /^[0-9a-zA-Z]*$/g
  598. return reg.test(value)
  599. }
  600. /**
  601. * 验证是否包含某个值
  602. */
  603. function contains(value, param) {
  604. return value.indexOf(param) >= 0
  605. }
  606. /**
  607. * 是否固定电话
  608. */
  609. function landline(value) {
  610. const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
  611. return reg.test(value)
  612. }
  613. /**
  614. * 判断是否为空
  615. */
  616. function empty(value) {
  617. switch (typeof value) {
  618. case 'undefined':
  619. return true
  620. case 'string':
  621. if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
  622. break
  623. case 'boolean':
  624. if (!value) return true
  625. break
  626. case 'number':
  627. if (value === 0 || isNaN(value)) return true
  628. break
  629. case 'object':
  630. if (value === null || value.length === 0) return true
  631. for (const i in value) {
  632. return false
  633. }
  634. return true
  635. }
  636. return false
  637. }
  638. /**
  639. * 是否json字符串
  640. */
  641. function jsonString(value) {
  642. if (typeof value === 'string') {
  643. try {
  644. const obj = JSON.parse(value)
  645. if (typeof obj === 'object' && obj) {
  646. return true
  647. }
  648. return false
  649. } catch (e) {
  650. return false
  651. }
  652. }
  653. return false
  654. }
  655. /**
  656. * 是否数组
  657. */
  658. function array(value) {
  659. if (typeof Array.isArray === 'function') {
  660. return Array.isArray(value)
  661. }
  662. return Object.prototype.toString.call(value) === '[object Array]'
  663. }
  664. /**
  665. * 是否对象
  666. */
  667. function object(value) {
  668. return Object.prototype.toString.call(value) === '[object Object]'
  669. }
  670. /**
  671. * 是否短信验证码
  672. */
  673. function code(value, len = 6) {
  674. return new RegExp(`^\\d{${len}}$`).test(value)
  675. }
  676. /**
  677. * 是否函数方法
  678. * @param {Object} value
  679. */
  680. function func(value) {
  681. return typeof value === 'function'
  682. }
  683. /**
  684. * 是否promise对象
  685. * @param {Object} value
  686. */
  687. function promise(value) {
  688. return object(value) && func(value.then) && func(value.catch)
  689. }
  690. /** 是否图片格式
  691. * @param {Object} value
  692. */
  693. function image(value) {
  694. const newValue = value.split('?')[0]
  695. const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
  696. return IMAGE_REGEXP.test(newValue)
  697. }
  698. /**
  699. * 是否视频格式
  700. * @param {Object} value
  701. */
  702. function video(value) {
  703. const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
  704. return VIDEO_REGEXP.test(value)
  705. }
  706. /**
  707. * 是否为正则对象
  708. * @param {Object}
  709. * @return {Boolean}
  710. */
  711. function regExp(o) {
  712. return o && Object.prototype.toString.call(o) === '[object RegExp]'
  713. }
  714. export default {
  715. range,
  716. sleep,
  717. random,
  718. guid,
  719. addStyle,
  720. deepClone,
  721. deepMerge,
  722. randomArray,
  723. timeFormat,
  724. timeFrom,
  725. trim,
  726. queryParams,
  727. padZero,
  728. getProperty,
  729. setProperty,
  730. debounce,
  731. throttle,
  732. email,
  733. mobile,
  734. url,
  735. date,
  736. dateISO,
  737. number,
  738. digits,
  739. idCard,
  740. carNo,
  741. amount,
  742. chinese,
  743. letter,
  744. enOrNum,
  745. contains,
  746. empty,
  747. isEmpty: empty,
  748. jsonString,
  749. landline,
  750. object,
  751. array,
  752. code,
  753. func,
  754. promise,
  755. video,
  756. image,
  757. regExp,
  758. string,
  759. }