移动端
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 

1220 行
30 KiB

  1. /**
  2. * 表格时间格式化
  3. */
  4. export function formatDate(cellValue) {
  5. if (cellValue == null || cellValue == "") return "";
  6. var date = new Date(cellValue)
  7. var year = date.getFullYear()
  8. var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
  9. var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
  10. var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
  11. var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
  12. var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
  13. return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
  14. }
  15. /**
  16. * @param {string} url
  17. * @returns {Object}
  18. */
  19. export function getQueryObject(url) {
  20. url = url == null ? window.location.href : url
  21. const search = url.substring(url.lastIndexOf('?') + 1)
  22. const obj = {}
  23. const reg = /([^?&=]+)=([^?&=]*)/g
  24. search.replace(reg, (rs, $1, $2) => {
  25. const name = decodeURIComponent($1)
  26. let val = decodeURIComponent($2)
  27. val = String(val)
  28. obj[name] = val
  29. return rs
  30. })
  31. return obj
  32. }
  33. /**
  34. * @param {string} input value
  35. * @returns {number} output value
  36. */
  37. export function byteLength(str) {
  38. // returns the byte length of an utf8 string
  39. let s = str.length
  40. for (var i = str.length - 1; i >= 0; i--) {
  41. const code = str.charCodeAt(i)
  42. if (code > 0x7f && code <= 0x7ff) s++
  43. else if (code > 0x7ff && code <= 0xffff) s += 2
  44. if (code >= 0xDC00 && code <= 0xDFFF) i--
  45. }
  46. return s
  47. }
  48. /**
  49. * @param {Array} actual
  50. * @returns {Array}
  51. */
  52. export function cleanArray(actual) {
  53. const newArray = []
  54. for (let i = 0; i < actual.length; i++) {
  55. if (actual[i]) {
  56. newArray.push(actual[i])
  57. }
  58. }
  59. return newArray
  60. }
  61. /**
  62. * @param {Object} json
  63. * @returns {Array}
  64. */
  65. export function param(json) {
  66. if (!json) return ''
  67. return cleanArray(
  68. Object.keys(json).map(key => {
  69. if (json[key] === undefined) return ''
  70. return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
  71. })
  72. ).join('&')
  73. }
  74. /**
  75. * @param {string} url
  76. * @returns {Object}
  77. */
  78. export function param2Obj(url) {
  79. const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
  80. if (!search) {
  81. return {}
  82. }
  83. const obj = {}
  84. const searchArr = search.split('&')
  85. searchArr.forEach(v => {
  86. const index = v.indexOf('=')
  87. if (index !== -1) {
  88. const name = v.substring(0, index)
  89. const val = v.substring(index + 1, v.length)
  90. obj[name] = val
  91. }
  92. })
  93. return obj
  94. }
  95. /**
  96. * @param {string} val
  97. * @returns {string}
  98. */
  99. export function html2Text(val) {
  100. const div = document.createElement('div')
  101. div.innerHTML = val
  102. return div.textContent || div.innerText
  103. }
  104. /**
  105. * Merges two objects, giving the last one precedence
  106. * @param {Object} target
  107. * @param {(Object|Array)} source
  108. * @returns {Object}
  109. */
  110. export function objectMerge(target, source) {
  111. if (typeof target !== 'object') {
  112. target = {}
  113. }
  114. if (Array.isArray(source)) {
  115. return source.slice()
  116. }
  117. Object.keys(source).forEach(property => {
  118. const sourceProperty = source[property]
  119. if (typeof sourceProperty === 'object') {
  120. target[property] = objectMerge(target[property], sourceProperty)
  121. } else {
  122. target[property] = sourceProperty
  123. }
  124. })
  125. return target
  126. }
  127. /**
  128. * @param {HTMLElement} element
  129. * @param {string} className
  130. */
  131. export function toggleClass(element, className) {
  132. if (!element || !className) {
  133. return
  134. }
  135. let classString = element.className
  136. const nameIndex = classString.indexOf(className)
  137. if (nameIndex === -1) {
  138. classString += '' + className
  139. } else {
  140. classString =
  141. classString.substr(0, nameIndex) +
  142. classString.substr(nameIndex + className.length)
  143. }
  144. element.className = classString
  145. }
  146. /**
  147. * @param {string} type
  148. * @returns {Date}
  149. */
  150. export function getTime(type) {
  151. if (type === 'start') {
  152. return new Date().getTime() - 3600 * 1000 * 24 * 90
  153. } else {
  154. return new Date(new Date().toDateString())
  155. }
  156. }
  157. /**
  158. * @param {Function} func
  159. * @param {number} wait
  160. * @param {boolean} immediate
  161. * @return {*}
  162. */
  163. export function debounce(func, wait, immediate) {
  164. let timeout, args, context, timestamp, result
  165. const later = function () {
  166. // 据上一次触发时间间隔
  167. const last = +new Date() - timestamp
  168. // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
  169. if (last < wait && last > 0) {
  170. timeout = setTimeout(later, wait - last)
  171. } else {
  172. timeout = null
  173. // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
  174. if (!immediate) {
  175. result = func.apply(context, args)
  176. if (!timeout) context = args = null
  177. }
  178. }
  179. }
  180. return function (...args) {
  181. context = this
  182. timestamp = +new Date()
  183. const callNow = immediate && !timeout
  184. // 如果延时不存在,重新设定延时
  185. if (!timeout) timeout = setTimeout(later, wait)
  186. if (callNow) {
  187. result = func.apply(context, args)
  188. context = args = null
  189. }
  190. return result
  191. }
  192. }
  193. /**
  194. * This is just a simple version of deep copy
  195. * Has a lot of edge cases bug
  196. * If you want to use a perfect deep copy, use lodash's _.cloneDeep
  197. * @param {Object} source
  198. * @returns {Object}
  199. */
  200. export function deepClone(source) {
  201. if (!source && typeof source !== 'object') {
  202. throw new Error('error arguments', 'deepClone')
  203. }
  204. const targetObj = source.constructor === Array ? [] : {}
  205. Object.keys(source).forEach(keys => {
  206. if (source[keys] && typeof source[keys] === 'object') {
  207. targetObj[keys] = deepClone(source[keys])
  208. } else {
  209. targetObj[keys] = source[keys]
  210. }
  211. })
  212. return targetObj
  213. }
  214. /**
  215. * @param {Array} arr
  216. * @returns {Array}
  217. */
  218. export function uniqueArr(arr) {
  219. return Array.from(new Set(arr))
  220. }
  221. /**
  222. * @returns {string}
  223. */
  224. export function createUniqueString() {
  225. const timestamp = +new Date() + ''
  226. const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  227. return (+(randomNum + timestamp)).toString(32)
  228. }
  229. /**
  230. * Check if an element has a class
  231. * @param {HTMLElement} elm
  232. * @param {string} cls
  233. * @returns {boolean}
  234. */
  235. export function hasClass(ele, cls) {
  236. return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
  237. }
  238. /**
  239. * Add class to element
  240. * @param {HTMLElement} elm
  241. * @param {string} cls
  242. */
  243. export function addClass(ele, cls) {
  244. if (!hasClass(ele, cls)) ele.className += ' ' + cls
  245. }
  246. /**
  247. * Remove class from element
  248. * @param {HTMLElement} elm
  249. * @param {string} cls
  250. */
  251. export function removeClass(ele, cls) {
  252. if (hasClass(ele, cls)) {
  253. const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
  254. ele.className = ele.className.replace(reg, ' ')
  255. }
  256. }
  257. export function makeMap(str, expectsLowerCase) {
  258. const map = Object.create(null)
  259. const list = str.split(',')
  260. for (let i = 0; i < list.length; i++) {
  261. map[list[i]] = true
  262. }
  263. return expectsLowerCase
  264. ? val => map[val.toLowerCase()]
  265. : val => map[val]
  266. }
  267. /*数字每隔3位一位小数*/
  268. export function numFormat(value) {
  269. if (value == null) {
  270. return "";
  271. }
  272. if (!value) return "0.00";
  273. value = value.toFixed(2);
  274. let is_neg = value < 0;
  275. var intPart = Math.abs(Math.trunc(value)); // 获取整数部分
  276. var intPartFormat = intPart.toString()
  277. .replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); // 将整数部分逢三一断
  278. if(is_neg)
  279. intPartFormat = '-' + intPartFormat;
  280. var floatPart = ".00"; // 预定义小数部分
  281. var value2Array = value.split(".");
  282. // =2表示数据有小数位
  283. if (value2Array.length === 2) {
  284. floatPart = value2Array[1].toString(); // 拿到小数部分
  285. if (floatPart.length === 1) {
  286. // 补0,实际上用不着
  287. return intPartFormat + "." + floatPart + "0";
  288. } else {
  289. return intPartFormat + "." + floatPart;
  290. }
  291. } else {
  292. return intPartFormat + floatPart;
  293. }
  294. }
  295. /* 文件大小格式化 */
  296. export function formatFileSize(size) {
  297. const Unit = ["Bytes", "Kb", "Mb", "Gb", "Tb"];
  298. //const Unit = ["byte", "K", "M", "G", "T"];
  299. let s, i;
  300. for(s = size, i = 0; s >= 1024 && i < Unit.length - 1; s /= 1024, i++);
  301. return s.toFixed(2).replace(/\.00$/, '') + Unit[i];
  302. }
  303. export function intFormat(value) {
  304. if (value == null) {
  305. return "";
  306. }
  307. if (!value) return "0"
  308. return Math.trunc(value)
  309. .toString()
  310. .replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); // 将整数部分逢三一断
  311. }
  312. /**
  313. * 支持的时间日期格式占位符:
  314. * 支持通用占位符和MySQL占位符(可以混合)
  315. * 格式化时以下都支持, 解析时不支持星期几
  316. * 不支持时区, 保留z Z zz ZZ zzz ZZZ zzzz ZZZZ %z %Z
  317. *
  318. * 4位年: yyyy %Y
  319. * 2位年: yy %y
  320. * 2位月: MM %m
  321. * 数字月: M %c
  322. * 英文月: MMMM %M
  323. * 简写英文月: MMM %b
  324. * 2位日: dd %d
  325. * 数字日: d
  326. * 2位时(24): HH %H
  327. * 数字时(24): H %k
  328. * 2位时(12): hh %I %h
  329. * 数字时(12): h %l
  330. * 2位分: mm ii %i
  331. * 数字分: m i
  332. * 2位秒: ss %s %S
  333. * 数字秒: s
  334. * 3位毫秒: sss
  335. * 小写上下午(AM/PM): a p
  336. * 大写上下午(AM/PM): A P %p
  337. * 星期几(周一为1, 周日为7): u
  338. * 星期几(周日为0): %w
  339. * 英文星期几: dddd %W
  340. * 简写英文星期几: ddd %a
  341. * %: %% // MySQL特殊占位符%
  342. */
  343. // Eng/lish
  344. const DATE_TIME_FORMAT_TYPE_IGNORE = 'ign';
  345. const DATE_TIME_FORMAT_TYPE_EXPRESSION = 'exp';
  346. const DATE_TIME_FORMAT_TYPE_RAW = 'raw';
  347. const DAYS_SIMPLE = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  348. const DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
  349. const MONTHS_SIMPLE = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  350. const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  351. function parseDateTimeFormatter(format)
  352. {
  353. let expect = function(target, str, range) {
  354. let i = 0;
  355. if(!range)
  356. range = 1;
  357. if(!Array.isArray(range))
  358. {
  359. let arr = [];
  360. for(let m = 1; m <= range; m++)
  361. arr.push(m);
  362. range = arr;
  363. }
  364. let res = 0;
  365. let max = Math.max(...range);
  366. let min = Math.min(...range);
  367. while(i < str.length)
  368. {
  369. let ch = str[i++];
  370. if(target.indexOf(ch) === -1)
  371. break;
  372. if(range.indexOf(i) === -1)
  373. {
  374. if(i >= max)
  375. break;
  376. }
  377. if(range.indexOf(i) !== -1)
  378. res = i;
  379. }
  380. if(res > 0)
  381. {
  382. return res;
  383. }
  384. return false;
  385. };
  386. let i = 0;
  387. let arr = [];
  388. while(i < format.length)
  389. {
  390. let ch = format[i];
  391. let n = false;
  392. switch(ch)
  393. {
  394. case 'y':
  395. n = expect('y', format.substr(i), [2, 4]);
  396. break;
  397. case 'M':
  398. n = expect('M', format.substr(i), 4);
  399. break;
  400. case 'd':
  401. n = expect('d', format.substr(i), 4);
  402. break;
  403. case 'H':
  404. case 'h':
  405. n = expect(ch, format.substr(i), 2);
  406. break;
  407. case 'm':
  408. case 'i':
  409. n = expect(ch, format.substr(i), 2);
  410. break;
  411. case 's':
  412. n = expect('s', format.substr(i), 3);
  413. break;
  414. case 'a':
  415. case 'p':
  416. case 'A':
  417. case 'P':
  418. case 'u':
  419. n = expect(ch, format.substr(i));
  420. break;
  421. case 'z':
  422. case 'Z':
  423. n = expect(ch, format.substr(i), 4);
  424. break;
  425. case '%':
  426. n = expect('YmdHisSyecklIh%zZ', format.substr(i + 1));
  427. if(n === 1)
  428. n++;
  429. break;
  430. default:
  431. arr.push({str: ch, type: DATE_TIME_FORMAT_TYPE_RAW});
  432. i++;
  433. continue;
  434. }
  435. if(n)
  436. {
  437. let s = format.substr(i, n);
  438. let ignore = ['z', 'zz', 'zzz', 'zzzz', 'Z', 'ZZ', 'ZZZ', 'ZZZZ', '%z', '%Z'].indexOf(s) !== -1;
  439. arr.push({str: s, type: ignore ? DATE_TIME_FORMAT_TYPE_IGNORE : DATE_TIME_FORMAT_TYPE_EXPRESSION});
  440. i += n;
  441. }
  442. else
  443. {
  444. arr.push({str: format.substr(i), type: DATE_TIME_FORMAT_TYPE_RAW});
  445. break;
  446. }
  447. }
  448. return arr;
  449. }
  450. /**
  451. * 格式化日期时间
  452. * @param date 日期时间 Date对象/时间戳 默认当前日期时间
  453. * @param format 格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss
  454. * @returns {string} 日期时间格式化后的字符串
  455. */
  456. export function date_format(date, format) {
  457. if(arguments.length === 1)
  458. {
  459. format = date;
  460. date = null;
  461. }
  462. if (!date)
  463. date = new Date;
  464. else if(!date instanceof Date)
  465. date = new Date(date);
  466. format = format || 'yyyy-MM-dd HH:mm:ss';
  467. let numpad = function(num, limit) {
  468. limit = limit || 10;
  469. if(num >= limit)
  470. return num;
  471. let res = num;
  472. while(num < limit)
  473. {
  474. res = '0' + res;
  475. limit /= 10;
  476. }
  477. return res;
  478. }
  479. const _y = date.getFullYear();
  480. const _m = date.getMonth() + 1;
  481. const _d = date.getDate();
  482. const _h = date.getHours();
  483. const _i = date.getMinutes();
  484. const _s = date.getSeconds();
  485. const _a = date.getDay();
  486. const _z = date.getMilliseconds();
  487. // General style
  488. let Options = {
  489. yyyy: _y,
  490. MM: numpad(_m),
  491. dd: numpad(_d),
  492. HH: numpad(_h),
  493. mm: numpad(_i),
  494. ss: numpad(_s),
  495. sss: numpad(_z, 100),
  496. yy: _y % 100,
  497. M: _m,
  498. d: _d,
  499. H: _h,
  500. m: _i,
  501. s: _s,
  502. hh: numpad((_h % 12) || 12),
  503. h: (_h % 12) || 12,
  504. // Qt style
  505. ddd: DAYS_SIMPLE[_a - 1],
  506. dddd: DAYS[_a - 1],
  507. MMM: MONTHS_SIMPLE[_m - 1],
  508. MMMM: MONTHS[_m - 1],
  509. // Java style
  510. a: _h > 12 ? 'pm' : 'am',
  511. A: _h > 12 ? 'PM' : 'AM',
  512. u: _a,
  513. };
  514. Options['p'] = Options.a;
  515. Options['P'] = Options.A;
  516. // PHP style
  517. Options['ii'] = Options.mm;
  518. Options['i'] = Options.m;
  519. // MySQL style
  520. Options['%Y'] = Options.yyyy;
  521. Options['%m'] = Options.MM;
  522. Options['%d'] = Options.dd;
  523. Options['%H'] = Options.HH;
  524. Options['%i'] = Options.mm;
  525. Options['%s'] = Options.ss;
  526. Options['%S'] = Options.ss;
  527. Options['%y'] = Options.yy;
  528. Options['%e'] = Options.d;
  529. Options['%c'] = Options.M;
  530. Options['%k'] = Options.H;
  531. Options['%l'] = Options.h;
  532. Options['%I'] = Options.hh;
  533. Options['%h'] = Options.hh;
  534. Options['%p'] = Options.A;
  535. Options['%w'] = Options.u - 1;
  536. Options['%a'] = Options.ddd;
  537. Options['%W'] = Options.dddd;
  538. Options['%M'] = Options.MMMM;
  539. Options['%b'] = Options.MMM;
  540. Options['%%'] = '%';
  541. let arr = parseDateTimeFormatter(format);
  542. //console.log(arr);
  543. arr = arr.filter((x) => x.type !== DATE_TIME_FORMAT_TYPE_IGNORE).map((x) => {
  544. return x.type === DATE_TIME_FORMAT_TYPE_EXPRESSION ? (Options[x.str] || x.str) : x.str;
  545. })
  546. //console.log(format, '|', arr.join(''));
  547. return arr.join('');
  548. }
  549. /**
  550. * 解析日期时间
  551. * @param date 日期时间字符串 字符串
  552. * @param format 格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss
  553. * @param initNow 缺省部分是否使用当前日期时间部分代替 bool 默认不使用当前
  554. * @returns {Date} 解析日期时间出来的Date对象
  555. */
  556. export function strtotime(date, format, initNow)
  557. {
  558. if (!date)
  559. return null;
  560. let expect = function(target, str) {
  561. if(Array.isArray(target))
  562. {
  563. let res = 0;
  564. if(typeof(target[0]) === 'number')
  565. {
  566. for(let t of target)
  567. {
  568. if(str.length >= t)
  569. {
  570. if(t > res && new RegExp(`^\\d{${t}}`).test(str))
  571. res = t;
  572. }
  573. }
  574. }
  575. else
  576. {
  577. for(let t of target)
  578. {
  579. if(str.length < t.length)
  580. continue;
  581. if(str.startsWith(t))
  582. {
  583. res = t.length;
  584. break;
  585. }
  586. }
  587. }
  588. return res;
  589. }
  590. else
  591. {
  592. if(typeof(target) === 'number')
  593. {
  594. if(str.length < target)
  595. return 0;
  596. if(!new RegExp(`^\\d{${target}}`).test(str))
  597. return null;
  598. return target;
  599. }
  600. else if(typeof(target) === 'object')
  601. {
  602. let res = 0;
  603. let min = target.min || 0;
  604. let max = target.max;
  605. for(let m = min; m <= max; m++)
  606. {
  607. let t = '' + m;
  608. if(str.length >= t.length)
  609. {
  610. if(str.startsWith(t))
  611. res = t.length;
  612. }
  613. }
  614. return res;
  615. }
  616. else
  617. {
  618. if(str.length < target.length)
  619. return 0;
  620. if(!str.startsWith(target))
  621. return 0;
  622. return target.length;
  623. }
  624. }
  625. };
  626. format = format || 'yyyy-MM-dd HH:mm:ss';
  627. let arr = parseDateTimeFormatter(format);
  628. let i = 0;
  629. let _y = undefined;
  630. let _m = undefined;
  631. let _d = undefined;
  632. let _h = undefined;
  633. let _i = undefined;
  634. let _s = undefined;
  635. let _z = undefined;
  636. let _h_12 = undefined;
  637. let _ap = undefined;
  638. let get_token = function(str, target) {
  639. let r = expect(target, date.substr(i));
  640. if(r <= 0)
  641. return null;
  642. let nstr = date.substr(i, r);
  643. i += r;
  644. return nstr;
  645. };
  646. //console.log(arr);
  647. for(let part of arr)
  648. {
  649. if(part.type === DATE_TIME_FORMAT_TYPE_RAW || part.type === DATE_TIME_FORMAT_TYPE_IGNORE)
  650. {
  651. let r = expect(part.str, date.substr(i));
  652. if(!r)
  653. return null;
  654. i += r;
  655. }
  656. else
  657. {
  658. let p = null;
  659. switch(part.str)
  660. {
  661. case 'yyyy':
  662. case '%Y':
  663. p = get_token(part.str, 4);
  664. if(p)
  665. _y = parseInt(p);
  666. break;
  667. case 'yy':
  668. case '%y':
  669. p = get_token(part.str, 2);
  670. if(p)
  671. _y = Math.floor((date.getFullYear()) / 100) * 100 + parseInt(p);
  672. break;
  673. case 'MM':
  674. case '%m':
  675. p = get_token(part.str, 2);
  676. if(p)
  677. _m = parseInt(p);
  678. break;
  679. case 'M':
  680. case '%c':
  681. p = get_token(part.str, {min: 1, max: 12});
  682. if(p)
  683. _m = parseInt(p);
  684. break;
  685. case 'MMMM':
  686. case '%M':
  687. p = get_token(part.str, MONTHS);
  688. if(p)
  689. _m = MONTHS.indexOf(p) + 1;
  690. break;
  691. case 'MMM':
  692. case '%b':
  693. p = get_token(part.str, MONTHS_SIMPLE);
  694. if(p)
  695. _m = MONTHS_SIMPLE.indexOf(p) + 1;
  696. break;
  697. case 'dd':
  698. case '%d':
  699. p = get_token(part.str, 2);
  700. if(p)
  701. _d = parseInt(p);
  702. break;
  703. case 'HH':
  704. case '%H':
  705. p = get_token(part.str, 2);
  706. if(p)
  707. _h = parseInt(p);
  708. break;
  709. case 'H':
  710. case '%k':
  711. p = get_token(part.str, {max: 23});
  712. if(p)
  713. _h = parseInt(p);
  714. break;
  715. case 'hh':
  716. case '%I':
  717. case '%h':
  718. p = get_token(part.str, 2);
  719. if(p)
  720. _h_12 = parseInt(p);
  721. break;
  722. case 'h':
  723. case '%l':
  724. p = get_token(part.str, {max: 12});
  725. if(p)
  726. _h_12 = parseInt(p);
  727. break;
  728. case 'mm':
  729. case 'ii':
  730. case '%i':
  731. p = get_token(part.str, 2);
  732. if(p)
  733. _i = parseInt(p);
  734. break;
  735. case 'm':
  736. case 'i':
  737. p = get_token(part.str, {max: 59});
  738. if(p)
  739. _i = parseInt(p);
  740. break;
  741. case 'ss':
  742. case '%s':
  743. case '%S':
  744. p = get_token(part.str, 2);
  745. if(p)
  746. _s = parseInt(p);
  747. break;
  748. case 's':
  749. p = get_token(part.str, {max: 59});
  750. if(p)
  751. _s = parseInt(p);
  752. break;
  753. case 'sss':
  754. p = get_token(part.str, {max: 999});
  755. if(p)
  756. _z = parseInt(p);
  757. break;
  758. case 'A':
  759. case 'p': {
  760. const AP = ['AM', 'PM'];
  761. p = get_token(part.str, AP);
  762. if(p)
  763. _ap = p.toLowerCase();
  764. }
  765. break;
  766. case 'a':
  767. case 'P':
  768. case '%p':{
  769. const AP = ['am', 'pm'];
  770. p = get_token(part.str, AP);
  771. if(p)
  772. _ap = p;
  773. }
  774. break;
  775. case 'u':
  776. case '%w':
  777. case '%W':
  778. case 'dddd':
  779. case 'ddd':
  780. throw new Error('不支持星期几解析: ' + part.str); // not ignore and throw
  781. //break;
  782. case '%%':
  783. //TODO: ignore 最好不解析出来
  784. break;
  785. default:
  786. throw new Error('不支持的格式解析: ' + part.str);
  787. break;
  788. }
  789. if(!p)
  790. return null;
  791. }
  792. }
  793. if(_h_12 !== undefined && _ap !== undefined)
  794. {
  795. _h = (_ap === 'pm' ? _h_12 + 12 : _h_12) % 24;
  796. }
  797. let res = new Date;
  798. //console.log('1111111111',_y, _m, _d, _h, _i, _s, _z);
  799. if(_y === undefined) _y = initNow ? res.getFullYear() : 0;
  800. if(_m === undefined) _m = initNow ? res.getMonth() + 1 : 1;
  801. if(_d === undefined) _d = initNow ? res.getDate() : 1;
  802. if(_h === undefined) _h = initNow ? res.getHours() : 0;
  803. if(_i === undefined) _i = initNow ? res.getMinutes() : 0;
  804. if(_s === undefined) _s = initNow ? res.getSeconds() : 0;
  805. if(_z === undefined) _z = initNow ? res.getMilliseconds() : 0;
  806. //console.log('2222222222',_y, _m, _d, _h, _i, _s, _z);
  807. res.setFullYear(_y, _m - 1, _d);
  808. res.setHours(_h, _i, _s, _z);
  809. return res;
  810. }
  811. /**
  812. * 转换日期时间格式
  813. * @param dateStr 源日期时间字符串 字符串
  814. * @param sourceFormat 源格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss
  815. * @param targetFormat 目标格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss
  816. * @param initNow 缺省部分是否使用当前日期时间部分代替 bool 默认不使用当前
  817. * @returns {string} 重新格式化的日期时间出字符串
  818. */
  819. export function date(dateStr, sourceFormat, targetFormat, initNow)
  820. {
  821. return date_format(strtotime(dateStr, sourceFormat, initNow), targetFormat);
  822. }
  823. /**
  824. * 自动生成多层级表头
  825. * @param printLines 表头数组
  826. * @param valueName 子级的属性名
  827. * @returns {
  828. * {
  829. * column: *[] 所有最底级的列,
  830. * colCount: number 列数,
  831. * header: *[] 表头 二维数组, 每一个成员数组是每一行tr, 其中每一个元素是每一个td, data是原始数组, colspan是td的colspan跨列数, rowspan是td的rowspan跨行数, hasChildren表示是否跨列
  832. * rowCount: number 行数
  833. * }
  834. * }
  835. *
  836. * 表头exam:
  837. let PrintLine = [
  838. { parameter: "bookDate", name: "日期", },
  839. { parameter: "subjectName", name: "科目名称", },
  840. { parameter: [
  841. { parameter: "jieQuantityNum", name: "数量", },
  842. { parameter: "jieQuantityUnit", name: "单位", },
  843. { parameter: [
  844. { parameter: "jieAmount", name: "借", },
  845. { parameter: "daiAmount", name: "贷", },
  846. ], name: "金额", },
  847. ], name: "入库",},
  848. { parameter: "ye", name: "余额" },
  849. ];
  850. ...
  851. let res = gen_multi_level_table_header(PrintLines, 'parameter');
  852. this.mHeaders = res.header;
  853. this.mColumns = res.column;
  854. this.list = [];
  855. ... 渲染
  856. <tr v-for="row in mHeaders">
  857. <td v-for="col in row"
  858. :style="col.data.style || {}"
  859. :colspan="col.colspan"
  860. :rowspan="col.rowspan"
  861. >
  862. {{ col.data.name }}
  863. </td>
  864. </tr>
  865. <tr v-for="item in list">
  866. <td v-for="val in mColumns">
  867. {{ item[val.parameter] }}
  868. </td>
  869. </tr>
  870. */
  871. export function gen_multi_level_table_header(printLines, valueName = 'value', labelName = undefined)
  872. {
  873. if(labelName === undefined)
  874. labelName = valueName;
  875. let headers = [];
  876. let columns = [];
  877. // 获取行数
  878. let maxRow_func = function(arr, start = 1) {
  879. let res = start;
  880. for(let v of arr)
  881. {
  882. if(Array.isArray(v[valueName]))
  883. {
  884. let r = maxRow_func(v[valueName], start + 1);
  885. if(r > res)
  886. res = r;
  887. }
  888. }
  889. return res;
  890. };
  891. let maxRow = maxRow_func(printLines);
  892. //console.log(maxRow);
  893. // 排列成2维数组
  894. let func = function(arr, col, row) {
  895. let res = [];
  896. let cols = 0;
  897. for(let i in arr)
  898. {
  899. let item = arr[i];
  900. if(Array.isArray(item[valueName]))
  901. {
  902. let c = func(item[valueName], i, row + 1);
  903. // delete newItem[valueName]; // 删除数组
  904. res.push({
  905. data: item,
  906. name: item[labelName],
  907. rowspan: 1,
  908. colspan: c,
  909. hasChildren: true,
  910. });
  911. cols += c;
  912. }
  913. else
  914. {
  915. res.push({
  916. data: item,
  917. name: item[labelName],
  918. rowspan: 1,
  919. colspan: 1,
  920. hasChildren: false,
  921. });
  922. columns.push(item);
  923. cols++;
  924. }
  925. }
  926. res.forEach((x) => {
  927. if(!x.hasChildren)
  928. x.rowspan = maxRow - row + 1; // min is 1
  929. });
  930. //console.log(res);
  931. if(!headers[row - 1])
  932. headers[row - 1] = [];
  933. headers[row - 1].push(...res);
  934. return cols;
  935. };
  936. let maxCol = func(printLines, 1, 1);
  937. //console.log(headers);
  938. return {
  939. header: headers,
  940. column: columns,
  941. rowCount: maxRow,
  942. colCount: maxCol,
  943. };
  944. }
  945. export function calc_eltable_rowspan(/*list: array, filedA, filedB, filedC...*/)
  946. {
  947. if(arguments.length < 2)
  948. return null;
  949. let list = arguments[0];
  950. let tableSpanConfig = {};
  951. let last = {};
  952. let last_key = {};
  953. for(let i = 1; i < arguments.length; i++)
  954. {
  955. let field = arguments[i];
  956. tableSpanConfig[field] = {};
  957. last[field] = null;
  958. last_key[field] = null;
  959. }
  960. if(list.length === 0)
  961. return tableSpanConfig;
  962. for (let i in list) {
  963. let item = list[i];
  964. for(let m = 1; m < arguments.length; m++)
  965. {
  966. let field = arguments[m];
  967. if (item[field] !== last[field]) {
  968. if (last_key[field] === null) {
  969. tableSpanConfig[field][last_key[field]] = 0;
  970. } else {
  971. tableSpanConfig[field][last_key[field]] = i - last_key[field];
  972. }
  973. last[field] = item[field];
  974. last_key[field] = i;
  975. }
  976. }
  977. }
  978. for(let i = 1; i < arguments.length; i++)
  979. {
  980. let field = arguments[i];
  981. if (last_key[field] !== null)
  982. tableSpanConfig[field][last_key[field]] = list.length - last_key[field];
  983. }
  984. return tableSpanConfig;
  985. }
  986. export function IS_DEVEL()
  987. {
  988. return process.env.NODE_ENV.toLowerCase() === 'development';
  989. }
  990. export function IS_TESTING()
  991. {
  992. return process.env.NODE_ENV.toLowerCase() === 'staging';
  993. }
  994. export function IS_STABLE()
  995. {
  996. return process.env.NODE_ENV.toLowerCase() === 'production';
  997. }
  998. export const exportDefault = 'export default '
  999. export const beautifierConf = {
  1000. html: {
  1001. indent_size: '2',
  1002. indent_char: ' ',
  1003. max_preserve_newlines: '-1',
  1004. preserve_newlines: false,
  1005. keep_array_indentation: false,
  1006. break_chained_methods: false,
  1007. indent_scripts: 'separate',
  1008. brace_style: 'end-expand',
  1009. space_before_conditional: true,
  1010. unescape_strings: false,
  1011. jslint_happy: false,
  1012. end_with_newline: true,
  1013. wrap_line_length: '110',
  1014. indent_inner_html: true,
  1015. comma_first: false,
  1016. e4x: true,
  1017. indent_empty_lines: true
  1018. },
  1019. js: {
  1020. indent_size: '2',
  1021. indent_char: ' ',
  1022. max_preserve_newlines: '-1',
  1023. preserve_newlines: false,
  1024. keep_array_indentation: false,
  1025. break_chained_methods: false,
  1026. indent_scripts: 'normal',
  1027. brace_style: 'end-expand',
  1028. space_before_conditional: true,
  1029. unescape_strings: false,
  1030. jslint_happy: true,
  1031. end_with_newline: true,
  1032. wrap_line_length: '110',
  1033. indent_inner_html: true,
  1034. comma_first: false,
  1035. e4x: true,
  1036. indent_empty_lines: true
  1037. }
  1038. }
  1039. // 首字母大小
  1040. export function titleCase(str) {
  1041. return str.replace(/( |^)[a-z]/g, L => L.toUpperCase())
  1042. }
  1043. // 下划转驼峰
  1044. export function camelCase(str) {
  1045. return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase())
  1046. }
  1047. export function isNumberStr(str) {
  1048. return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
  1049. }
  1050. export function parse_IDcard(idcard) {
  1051. if(!idcard)
  1052. return false;
  1053. if(idcard.length !== 18)
  1054. return false;
  1055. if(!/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(idcard))
  1056. return false;
  1057. let sex = (parseInt(idcard.substr(16, 1)) % 2) ^ 1;
  1058. let now = new Date().getFullYear();
  1059. let y = parseInt(idcard.substr(6, 4));
  1060. let age = Math.max(now - y, 0);
  1061. return [sex, age];
  1062. }
  1063. export const PROPOSER_VIEW = 1;
  1064. export const PROPOSER_EDIT = 2;
  1065. export const PROPOSER_ADD = 3;
  1066. export const APPLY_DRAFT = "1";
  1067. export const GROUP_AUDITING = "32";
  1068. export const GROUP_AUDITED = "2";
  1069. export const GROUP_ANNOUNCING = "3";
  1070. export const GROUP_ANNOUNCING_END = "33";
  1071. export const VILLAGE_AUDITING = "31";
  1072. export const VILLAGE_AUDITED = "4";
  1073. export const VILLAGE_ANNOUNCING = "5";
  1074. export const VILLAGE_ANNOUNCING_END = "34";
  1075. export const COUNTY_RECEIVE = "6";
  1076. export const FIRST_PRESENT = "7";
  1077. export const COUNTY_AUDITING = "8";
  1078. export const COUNTY_ANNOUNCING = "9";
  1079. export const APPLY_AUDITED = "10";
  1080. export const DISTRIBUTE_LICENSE = "11";
  1081. export const START_DRAFT = "12";
  1082. export const START_AUDITING = "13";
  1083. export const START_GROUP_AUDITED = "14";
  1084. export const START_VILLAGE_AUDITED = "15";
  1085. export const START_COUNTY_RECEIVE = "16";
  1086. export const SECOND_PRESENT = "17";
  1087. export const PRESENT_LEADER_AUDITED = "28";
  1088. export const FOUNDATION_PRESENT = "19";
  1089. export const START_AUDITED = "18";
  1090. export const ACCEPTANCE_DRAFT = "20";
  1091. export const ACCEPTANCE_AUDITING = "21";
  1092. export const ACCEPTANCE_GROUP_AUDITED = "22";
  1093. export const ACCEPTANCE_VILLAGE_AUDITED = "23";
  1094. export const ACCEPTANCE_COUNTY_RECEIVE = "24";
  1095. export const THIRD_PRESENT = "25";
  1096. export const ACCEPTANCE_PRESENT_LEADER_AUDIT = "30";
  1097. export const ACCEPTANCE_COUNTY_AUDITING = "29";
  1098. export const ACCEPTANCE_AUDITED = "26";
  1099. export const FILED_FINISH = "27";
  1100. export function make_tree(list, parentId, config)
  1101. {
  1102. parentId = parentId !== undefined ? parentId : null;
  1103. let idName = 'id', parentIdName = 'parentId', childrenName = 'children';
  1104. if(config && Object.prototype.toString.call(config).toLowerCase() === '[object object]')
  1105. {
  1106. if(config.id) idName = config.id;
  1107. if(config.parentId) parentIdName = config.parentId;
  1108. if(config.children) childrenName = config.children;
  1109. }
  1110. return list.filter((x) => parentId == x[parentIdName])
  1111. .map((x) => {
  1112. let arr = make_tree(list, x[idName], config);
  1113. if(arr && arr.length > 0)
  1114. x[childrenName] = arr;
  1115. return x;
  1116. })
  1117. ;
  1118. }
  1119. export function array_grouping(arr, byFunc)
  1120. {
  1121. let res = {};
  1122. arr.forEach((x) => {
  1123. let a = byFunc(x);
  1124. if(res.hasOwnProperty(a))
  1125. res[a].push(x);
  1126. else
  1127. res[a] = [x];
  1128. });
  1129. return res;
  1130. }
  1131. export function array_grouping2(arr, byFunc, keyName = 'key', valueName = 'value')
  1132. {
  1133. let res = {};
  1134. let r = [];
  1135. arr.forEach((x) => {
  1136. let a = byFunc(x);
  1137. if(res.hasOwnProperty(a))
  1138. res[a].push(x);
  1139. else
  1140. {
  1141. let tmp = [x];
  1142. res[a] = tmp;
  1143. let obj = {};
  1144. obj[keyName || 'key'] = a;
  1145. obj[valueName || 'value'] = tmp;
  1146. r.push(obj);
  1147. }
  1148. });
  1149. return r;
  1150. }
  1151. export function manual_page(list, page_no = 1, page_size = 10)
  1152. {
  1153. let start = (page_no - 1) * page_size;
  1154. return list.slice(start, start + page_size);
  1155. }
  1156. export function array_toMap(arr, byFunc, overriding)
  1157. {
  1158. let res = {};
  1159. arr.forEach((x) => {
  1160. let a = byFunc(x);
  1161. if(!res.hasOwnProperty(a) || overriding)
  1162. res[a] = x;
  1163. });
  1164. return res;
  1165. }