/** * 表格时间格式化 */ export function formatDate(cellValue) { if (cellValue == null || cellValue == "") return ""; var date = new Date(cellValue) var year = date.getFullYear() var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds } /** * @param {string} url * @returns {Object} */ export function getQueryObject(url) { url = url == null ? window.location.href : url const search = url.substring(url.lastIndexOf('?') + 1) const obj = {} const reg = /([^?&=]+)=([^?&=]*)/g search.replace(reg, (rs, $1, $2) => { const name = decodeURIComponent($1) let val = decodeURIComponent($2) val = String(val) obj[name] = val return rs }) return obj } /** * @param {string} input value * @returns {number} output value */ export function byteLength(str) { // returns the byte length of an utf8 string let s = str.length for (var i = str.length - 1; i >= 0; i--) { const code = str.charCodeAt(i) if (code > 0x7f && code <= 0x7ff) s++ else if (code > 0x7ff && code <= 0xffff) s += 2 if (code >= 0xDC00 && code <= 0xDFFF) i-- } return s } /** * @param {Array} actual * @returns {Array} */ export function cleanArray(actual) { const newArray = [] for (let i = 0; i < actual.length; i++) { if (actual[i]) { newArray.push(actual[i]) } } return newArray } /** * @param {Object} json * @returns {Array} */ export function param(json) { if (!json) return '' return cleanArray( Object.keys(json).map(key => { if (json[key] === undefined) return '' return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) }) ).join('&') } /** * @param {string} url * @returns {Object} */ export function param2Obj(url) { const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') if (!search) { return {} } const obj = {} const searchArr = search.split('&') searchArr.forEach(v => { const index = v.indexOf('=') if (index !== -1) { const name = v.substring(0, index) const val = v.substring(index + 1, v.length) obj[name] = val } }) return obj } /** * @param {string} val * @returns {string} */ export function html2Text(val) { const div = document.createElement('div') div.innerHTML = val return div.textContent || div.innerText } /** * Merges two objects, giving the last one precedence * @param {Object} target * @param {(Object|Array)} source * @returns {Object} */ export function objectMerge(target, source) { if (typeof target !== 'object') { target = {} } if (Array.isArray(source)) { return source.slice() } Object.keys(source).forEach(property => { const sourceProperty = source[property] if (typeof sourceProperty === 'object') { target[property] = objectMerge(target[property], sourceProperty) } else { target[property] = sourceProperty } }) return target } /** * @param {HTMLElement} element * @param {string} className */ export function toggleClass(element, className) { if (!element || !className) { return } let classString = element.className const nameIndex = classString.indexOf(className) if (nameIndex === -1) { classString += '' + className } else { classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length) } element.className = classString } /** * @param {string} type * @returns {Date} */ export function getTime(type) { if (type === 'start') { return new Date().getTime() - 3600 * 1000 * 24 * 90 } else { return new Date(new Date().toDateString()) } } /** * @param {Function} func * @param {number} wait * @param {boolean} immediate * @return {*} */ export function debounce(func, wait, immediate) { let timeout, args, context, timestamp, result const later = function () { // 据上一次触发时间间隔 const last = +new Date() - timestamp // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { timeout = setTimeout(later, wait - last) } else { timeout = null // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { result = func.apply(context, args) if (!timeout) context = args = null } } } return function (...args) { context = this timestamp = +new Date() const callNow = immediate && !timeout // 如果延时不存在,重新设定延时 if (!timeout) timeout = setTimeout(later, wait) if (callNow) { result = func.apply(context, args) context = args = null } return result } } /** * This is just a simple version of deep copy * Has a lot of edge cases bug * If you want to use a perfect deep copy, use lodash's _.cloneDeep * @param {Object} source * @returns {Object} */ export function deepClone(source) { if (!source && typeof source !== 'object') { throw new Error('error arguments', 'deepClone') } const targetObj = source.constructor === Array ? [] : {} Object.keys(source).forEach(keys => { if (source[keys] && typeof source[keys] === 'object') { targetObj[keys] = deepClone(source[keys]) } else { targetObj[keys] = source[keys] } }) return targetObj } /** * @param {Array} arr * @returns {Array} */ export function uniqueArr(arr) { return Array.from(new Set(arr)) } /** * @returns {string} */ export function createUniqueString() { const timestamp = +new Date() + '' const randomNum = parseInt((1 + Math.random()) * 65536) + '' return (+(randomNum + timestamp)).toString(32) } /** * Check if an element has a class * @param {HTMLElement} elm * @param {string} cls * @returns {boolean} */ export function hasClass(ele, cls) { return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) } /** * Add class to element * @param {HTMLElement} elm * @param {string} cls */ export function addClass(ele, cls) { if (!hasClass(ele, cls)) ele.className += ' ' + cls } /** * Remove class from element * @param {HTMLElement} elm * @param {string} cls */ export function removeClass(ele, cls) { if (hasClass(ele, cls)) { const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') ele.className = ele.className.replace(reg, ' ') } } export function makeMap(str, expectsLowerCase) { const map = Object.create(null) const list = str.split(',') for (let i = 0; i < list.length; i++) { map[list[i]] = true } return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val] } /*数字每隔3位一位小数*/ export function numFormat(value) { if (value == null) { return ""; } if (!value) return "0.00"; value = value.toFixed(2); let is_neg = value < 0; var intPart = Math.abs(Math.trunc(value)); // 获取整数部分 var intPartFormat = intPart.toString() .replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); // 将整数部分逢三一断 if(is_neg) intPartFormat = '-' + intPartFormat; var floatPart = ".00"; // 预定义小数部分 var value2Array = value.split("."); // =2表示数据有小数位 if (value2Array.length === 2) { floatPart = value2Array[1].toString(); // 拿到小数部分 if (floatPart.length === 1) { // 补0,实际上用不着 return intPartFormat + "." + floatPart + "0"; } else { return intPartFormat + "." + floatPart; } } else { return intPartFormat + floatPart; } } /* 文件大小格式化 */ export function formatFileSize(size) { const Unit = ["Bytes", "Kb", "Mb", "Gb", "Tb"]; //const Unit = ["byte", "K", "M", "G", "T"]; let s, i; for(s = size, i = 0; s >= 1024 && i < Unit.length - 1; s /= 1024, i++); return s.toFixed(2).replace(/\.00$/, '') + Unit[i]; } export function intFormat(value) { if (value == null) { return ""; } if (!value) return "0" return Math.trunc(value) .toString() .replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); // 将整数部分逢三一断 } /** * 支持的时间日期格式占位符: * 支持通用占位符和MySQL占位符(可以混合) * 格式化时以下都支持, 解析时不支持星期几 * 不支持时区, 保留z Z zz ZZ zzz ZZZ zzzz ZZZZ %z %Z * * 4位年: yyyy %Y * 2位年: yy %y * 2位月: MM %m * 数字月: M %c * 英文月: MMMM %M * 简写英文月: MMM %b * 2位日: dd %d * 数字日: d * 2位时(24): HH %H * 数字时(24): H %k * 2位时(12): hh %I %h * 数字时(12): h %l * 2位分: mm ii %i * 数字分: m i * 2位秒: ss %s %S * 数字秒: s * 3位毫秒: sss * 小写上下午(AM/PM): a p * 大写上下午(AM/PM): A P %p * 星期几(周一为1, 周日为7): u * 星期几(周日为0): %w * 英文星期几: dddd %W * 简写英文星期几: ddd %a * %: %% // MySQL特殊占位符% */ // Eng/lish const DATE_TIME_FORMAT_TYPE_IGNORE = 'ign'; const DATE_TIME_FORMAT_TYPE_EXPRESSION = 'exp'; const DATE_TIME_FORMAT_TYPE_RAW = 'raw'; const DAYS_SIMPLE = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; const DAYS = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']; const MONTHS_SIMPLE = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; function parseDateTimeFormatter(format) { let expect = function(target, str, range) { let i = 0; if(!range) range = 1; if(!Array.isArray(range)) { let arr = []; for(let m = 1; m <= range; m++) arr.push(m); range = arr; } let res = 0; let max = Math.max(...range); let min = Math.min(...range); while(i < str.length) { let ch = str[i++]; if(target.indexOf(ch) === -1) break; if(range.indexOf(i) === -1) { if(i >= max) break; } if(range.indexOf(i) !== -1) res = i; } if(res > 0) { return res; } return false; }; let i = 0; let arr = []; while(i < format.length) { let ch = format[i]; let n = false; switch(ch) { case 'y': n = expect('y', format.substr(i), [2, 4]); break; case 'M': n = expect('M', format.substr(i), 4); break; case 'd': n = expect('d', format.substr(i), 4); break; case 'H': case 'h': n = expect(ch, format.substr(i), 2); break; case 'm': case 'i': n = expect(ch, format.substr(i), 2); break; case 's': n = expect('s', format.substr(i), 3); break; case 'a': case 'p': case 'A': case 'P': case 'u': n = expect(ch, format.substr(i)); break; case 'z': case 'Z': n = expect(ch, format.substr(i), 4); break; case '%': n = expect('YmdHisSyecklIh%zZ', format.substr(i + 1)); if(n === 1) n++; break; default: arr.push({str: ch, type: DATE_TIME_FORMAT_TYPE_RAW}); i++; continue; } if(n) { let s = format.substr(i, n); let ignore = ['z', 'zz', 'zzz', 'zzzz', 'Z', 'ZZ', 'ZZZ', 'ZZZZ', '%z', '%Z'].indexOf(s) !== -1; arr.push({str: s, type: ignore ? DATE_TIME_FORMAT_TYPE_IGNORE : DATE_TIME_FORMAT_TYPE_EXPRESSION}); i += n; } else { arr.push({str: format.substr(i), type: DATE_TIME_FORMAT_TYPE_RAW}); break; } } return arr; } /** * 格式化日期时间 * @param date 日期时间 Date对象/时间戳 默认当前日期时间 * @param format 格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss * @returns {string} 日期时间格式化后的字符串 */ export function date_format(date, format) { if(arguments.length === 1) { format = date; date = null; } if (!date) date = new Date; else if(!date instanceof Date) date = new Date(date); format = format || 'yyyy-MM-dd HH:mm:ss'; let numpad = function(num, limit) { limit = limit || 10; if(num >= limit) return num; let res = num; while(num < limit) { res = '0' + res; limit /= 10; } return res; } const _y = date.getFullYear(); const _m = date.getMonth() + 1; const _d = date.getDate(); const _h = date.getHours(); const _i = date.getMinutes(); const _s = date.getSeconds(); const _a = date.getDay(); const _z = date.getMilliseconds(); // General style let Options = { yyyy: _y, MM: numpad(_m), dd: numpad(_d), HH: numpad(_h), mm: numpad(_i), ss: numpad(_s), sss: numpad(_z, 100), yy: _y % 100, M: _m, d: _d, H: _h, m: _i, s: _s, hh: numpad((_h % 12) || 12), h: (_h % 12) || 12, // Qt style ddd: DAYS_SIMPLE[_a - 1], dddd: DAYS[_a - 1], MMM: MONTHS_SIMPLE[_m - 1], MMMM: MONTHS[_m - 1], // Java style a: _h > 12 ? 'pm' : 'am', A: _h > 12 ? 'PM' : 'AM', u: _a, }; Options['p'] = Options.a; Options['P'] = Options.A; // PHP style Options['ii'] = Options.mm; Options['i'] = Options.m; // MySQL style Options['%Y'] = Options.yyyy; Options['%m'] = Options.MM; Options['%d'] = Options.dd; Options['%H'] = Options.HH; Options['%i'] = Options.mm; Options['%s'] = Options.ss; Options['%S'] = Options.ss; Options['%y'] = Options.yy; Options['%e'] = Options.d; Options['%c'] = Options.M; Options['%k'] = Options.H; Options['%l'] = Options.h; Options['%I'] = Options.hh; Options['%h'] = Options.hh; Options['%p'] = Options.A; Options['%w'] = Options.u - 1; Options['%a'] = Options.ddd; Options['%W'] = Options.dddd; Options['%M'] = Options.MMMM; Options['%b'] = Options.MMM; Options['%%'] = '%'; let arr = parseDateTimeFormatter(format); //console.log(arr); arr = arr.filter((x) => x.type !== DATE_TIME_FORMAT_TYPE_IGNORE).map((x) => { return x.type === DATE_TIME_FORMAT_TYPE_EXPRESSION ? (Options[x.str] || x.str) : x.str; }) //console.log(format, '|', arr.join('')); return arr.join(''); } /** * 解析日期时间 * @param date 日期时间字符串 字符串 * @param format 格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss * @param initNow 缺省部分是否使用当前日期时间部分代替 bool 默认不使用当前 * @returns {Date} 解析日期时间出来的Date对象 */ export function strtotime(date, format, initNow) { if (!date) return null; let expect = function(target, str) { if(Array.isArray(target)) { let res = 0; if(typeof(target[0]) === 'number') { for(let t of target) { if(str.length >= t) { if(t > res && new RegExp(`^\\d{${t}}`).test(str)) res = t; } } } else { for(let t of target) { if(str.length < t.length) continue; if(str.startsWith(t)) { res = t.length; break; } } } return res; } else { if(typeof(target) === 'number') { if(str.length < target) return 0; if(!new RegExp(`^\\d{${target}}`).test(str)) return null; return target; } else if(typeof(target) === 'object') { let res = 0; let min = target.min || 0; let max = target.max; for(let m = min; m <= max; m++) { let t = '' + m; if(str.length >= t.length) { if(str.startsWith(t)) res = t.length; } } return res; } else { if(str.length < target.length) return 0; if(!str.startsWith(target)) return 0; return target.length; } } }; format = format || 'yyyy-MM-dd HH:mm:ss'; let arr = parseDateTimeFormatter(format); let i = 0; let _y = undefined; let _m = undefined; let _d = undefined; let _h = undefined; let _i = undefined; let _s = undefined; let _z = undefined; let _h_12 = undefined; let _ap = undefined; let get_token = function(str, target) { let r = expect(target, date.substr(i)); if(r <= 0) return null; let nstr = date.substr(i, r); i += r; return nstr; }; //console.log(arr); for(let part of arr) { if(part.type === DATE_TIME_FORMAT_TYPE_RAW || part.type === DATE_TIME_FORMAT_TYPE_IGNORE) { let r = expect(part.str, date.substr(i)); if(!r) return null; i += r; } else { let p = null; switch(part.str) { case 'yyyy': case '%Y': p = get_token(part.str, 4); if(p) _y = parseInt(p); break; case 'yy': case '%y': p = get_token(part.str, 2); if(p) _y = Math.floor((date.getFullYear()) / 100) * 100 + parseInt(p); break; case 'MM': case '%m': p = get_token(part.str, 2); if(p) _m = parseInt(p); break; case 'M': case '%c': p = get_token(part.str, {min: 1, max: 12}); if(p) _m = parseInt(p); break; case 'MMMM': case '%M': p = get_token(part.str, MONTHS); if(p) _m = MONTHS.indexOf(p) + 1; break; case 'MMM': case '%b': p = get_token(part.str, MONTHS_SIMPLE); if(p) _m = MONTHS_SIMPLE.indexOf(p) + 1; break; case 'dd': case '%d': p = get_token(part.str, 2); if(p) _d = parseInt(p); break; case 'HH': case '%H': p = get_token(part.str, 2); if(p) _h = parseInt(p); break; case 'H': case '%k': p = get_token(part.str, {max: 23}); if(p) _h = parseInt(p); break; case 'hh': case '%I': case '%h': p = get_token(part.str, 2); if(p) _h_12 = parseInt(p); break; case 'h': case '%l': p = get_token(part.str, {max: 12}); if(p) _h_12 = parseInt(p); break; case 'mm': case 'ii': case '%i': p = get_token(part.str, 2); if(p) _i = parseInt(p); break; case 'm': case 'i': p = get_token(part.str, {max: 59}); if(p) _i = parseInt(p); break; case 'ss': case '%s': case '%S': p = get_token(part.str, 2); if(p) _s = parseInt(p); break; case 's': p = get_token(part.str, {max: 59}); if(p) _s = parseInt(p); break; case 'sss': p = get_token(part.str, {max: 999}); if(p) _z = parseInt(p); break; case 'A': case 'p': { const AP = ['AM', 'PM']; p = get_token(part.str, AP); if(p) _ap = p.toLowerCase(); } break; case 'a': case 'P': case '%p':{ const AP = ['am', 'pm']; p = get_token(part.str, AP); if(p) _ap = p; } break; case 'u': case '%w': case '%W': case 'dddd': case 'ddd': throw new Error('不支持星期几解析: ' + part.str); // not ignore and throw //break; case '%%': //TODO: ignore 最好不解析出来 break; default: throw new Error('不支持的格式解析: ' + part.str); break; } if(!p) return null; } } if(_h_12 !== undefined && _ap !== undefined) { _h = (_ap === 'pm' ? _h_12 + 12 : _h_12) % 24; } let res = new Date; //console.log('1111111111',_y, _m, _d, _h, _i, _s, _z); if(_y === undefined) _y = initNow ? res.getFullYear() : 0; if(_m === undefined) _m = initNow ? res.getMonth() + 1 : 1; if(_d === undefined) _d = initNow ? res.getDate() : 1; if(_h === undefined) _h = initNow ? res.getHours() : 0; if(_i === undefined) _i = initNow ? res.getMinutes() : 0; if(_s === undefined) _s = initNow ? res.getSeconds() : 0; if(_z === undefined) _z = initNow ? res.getMilliseconds() : 0; //console.log('2222222222',_y, _m, _d, _h, _i, _s, _z); res.setFullYear(_y, _m - 1, _d); res.setHours(_h, _i, _s, _z); return res; } /** * 转换日期时间格式 * @param dateStr 源日期时间字符串 字符串 * @param sourceFormat 源格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss * @param targetFormat 目标格式化字符串 字符串 默认 yyyy-MM-dd HH:mm:ss * @param initNow 缺省部分是否使用当前日期时间部分代替 bool 默认不使用当前 * @returns {string} 重新格式化的日期时间出字符串 */ export function date(dateStr, sourceFormat, targetFormat, initNow) { return date_format(strtotime(dateStr, sourceFormat, initNow), targetFormat); } /** * 自动生成多层级表头 * @param printLines 表头数组 * @param valueName 子级的属性名 * @returns { * { * column: *[] 所有最底级的列, * colCount: number 列数, * header: *[] 表头 二维数组, 每一个成员数组是每一行tr, 其中每一个元素是每一个td, data是原始数组, colspan是td的colspan跨列数, rowspan是td的rowspan跨行数, hasChildren表示是否跨列 * rowCount: number 行数 * } * } * * 表头exam: let PrintLine = [ { parameter: "bookDate", name: "日期", }, { parameter: "subjectName", name: "科目名称", }, { parameter: [ { parameter: "jieQuantityNum", name: "数量", }, { parameter: "jieQuantityUnit", name: "单位", }, { parameter: [ { parameter: "jieAmount", name: "借", }, { parameter: "daiAmount", name: "贷", }, ], name: "金额", }, ], name: "入库",}, { parameter: "ye", name: "余额" }, ]; ... let res = gen_multi_level_table_header(PrintLines, 'parameter'); this.mHeaders = res.header; this.mColumns = res.column; this.list = []; ... 渲染 {{ col.data.name }} {{ item[val.parameter] }} */ export function gen_multi_level_table_header(printLines, valueName = 'value', labelName = undefined) { if(labelName === undefined) labelName = valueName; let headers = []; let columns = []; // 获取行数 let maxRow_func = function(arr, start = 1) { let res = start; for(let v of arr) { if(Array.isArray(v[valueName])) { let r = maxRow_func(v[valueName], start + 1); if(r > res) res = r; } } return res; }; let maxRow = maxRow_func(printLines); //console.log(maxRow); // 排列成2维数组 let func = function(arr, col, row) { let res = []; let cols = 0; for(let i in arr) { let item = arr[i]; if(Array.isArray(item[valueName])) { let c = func(item[valueName], i, row + 1); // delete newItem[valueName]; // 删除数组 res.push({ data: item, name: item[labelName], rowspan: 1, colspan: c, hasChildren: true, }); cols += c; } else { res.push({ data: item, name: item[labelName], rowspan: 1, colspan: 1, hasChildren: false, }); columns.push(item); cols++; } } res.forEach((x) => { if(!x.hasChildren) x.rowspan = maxRow - row + 1; // min is 1 }); //console.log(res); if(!headers[row - 1]) headers[row - 1] = []; headers[row - 1].push(...res); return cols; }; let maxCol = func(printLines, 1, 1); //console.log(headers); return { header: headers, column: columns, rowCount: maxRow, colCount: maxCol, }; } export function calc_eltable_rowspan(/*list: array, filedA, filedB, filedC...*/) { if(arguments.length < 2) return null; let list = arguments[0]; let tableSpanConfig = {}; let last = {}; let last_key = {}; for(let i = 1; i < arguments.length; i++) { let field = arguments[i]; tableSpanConfig[field] = {}; last[field] = null; last_key[field] = null; } if(list.length === 0) return tableSpanConfig; for (let i in list) { let item = list[i]; for(let m = 1; m < arguments.length; m++) { let field = arguments[m]; if (item[field] !== last[field]) { if (last_key[field] === null) { tableSpanConfig[field][last_key[field]] = 0; } else { tableSpanConfig[field][last_key[field]] = i - last_key[field]; } last[field] = item[field]; last_key[field] = i; } } } for(let i = 1; i < arguments.length; i++) { let field = arguments[i]; if (last_key[field] !== null) tableSpanConfig[field][last_key[field]] = list.length - last_key[field]; } return tableSpanConfig; } export function IS_DEVEL() { return process.env.NODE_ENV.toLowerCase() === 'development'; } export function IS_TESTING() { return process.env.NODE_ENV.toLowerCase() === 'staging'; } export function IS_STABLE() { return process.env.NODE_ENV.toLowerCase() === 'production'; } export const exportDefault = 'export default ' export const beautifierConf = { html: { indent_size: '2', indent_char: ' ', max_preserve_newlines: '-1', preserve_newlines: false, keep_array_indentation: false, break_chained_methods: false, indent_scripts: 'separate', brace_style: 'end-expand', space_before_conditional: true, unescape_strings: false, jslint_happy: false, end_with_newline: true, wrap_line_length: '110', indent_inner_html: true, comma_first: false, e4x: true, indent_empty_lines: true }, js: { indent_size: '2', indent_char: ' ', max_preserve_newlines: '-1', preserve_newlines: false, keep_array_indentation: false, break_chained_methods: false, indent_scripts: 'normal', brace_style: 'end-expand', space_before_conditional: true, unescape_strings: false, jslint_happy: true, end_with_newline: true, wrap_line_length: '110', indent_inner_html: true, comma_first: false, e4x: true, indent_empty_lines: true } } // 首字母大小 export function titleCase(str) { return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) } // 下划转驼峰 export function camelCase(str) { return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase()) } export function isNumberStr(str) { return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) } export function parse_IDcard(idcard) { if(!idcard) return false; if(idcard.length !== 18) return false; 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)) return false; let sex = (parseInt(idcard.substr(16, 1)) % 2) ^ 1; let now = new Date().getFullYear(); let y = parseInt(idcard.substr(6, 4)); let age = Math.max(now - y, 0); return [sex, age]; } export const PROPOSER_VIEW = 1; export const PROPOSER_EDIT = 2; export const PROPOSER_ADD = 3; export const APPLY_DRAFT = "1"; export const GROUP_AUDITING = "32"; export const GROUP_AUDITED = "2"; export const GROUP_ANNOUNCING = "3"; export const GROUP_ANNOUNCING_END = "33"; export const VILLAGE_AUDITING = "31"; export const VILLAGE_AUDITED = "4"; export const VILLAGE_ANNOUNCING = "5"; export const VILLAGE_ANNOUNCING_END = "34"; export const COUNTY_RECEIVE = "6"; export const FIRST_PRESENT = "7"; export const COUNTY_AUDITING = "8"; export const COUNTY_ANNOUNCING = "9"; export const APPLY_AUDITED = "10"; export const DISTRIBUTE_LICENSE = "11"; export const START_DRAFT = "12"; export const START_AUDITING = "13"; export const START_GROUP_AUDITED = "14"; export const START_VILLAGE_AUDITED = "15"; export const START_COUNTY_RECEIVE = "16"; export const SECOND_PRESENT = "17"; export const PRESENT_LEADER_AUDITED = "28"; export const FOUNDATION_PRESENT = "19"; export const START_AUDITED = "18"; export const ACCEPTANCE_DRAFT = "20"; export const ACCEPTANCE_AUDITING = "21"; export const ACCEPTANCE_GROUP_AUDITED = "22"; export const ACCEPTANCE_VILLAGE_AUDITED = "23"; export const ACCEPTANCE_COUNTY_RECEIVE = "24"; export const THIRD_PRESENT = "25"; export const ACCEPTANCE_PRESENT_LEADER_AUDIT = "30"; export const ACCEPTANCE_COUNTY_AUDITING = "29"; export const ACCEPTANCE_AUDITED = "26"; export const FILED_FINISH = "27"; export function make_tree(list, parentId, config) { parentId = parentId !== undefined ? parentId : null; let idName = 'id', parentIdName = 'parentId', childrenName = 'children'; if(config && Object.prototype.toString.call(config).toLowerCase() === '[object object]') { if(config.id) idName = config.id; if(config.parentId) parentIdName = config.parentId; if(config.children) childrenName = config.children; } return list.filter((x) => parentId == x[parentIdName]) .map((x) => { let arr = make_tree(list, x[idName], config); if(arr && arr.length > 0) x[childrenName] = arr; return x; }) ; } export function array_grouping(arr, byFunc) { let res = {}; arr.forEach((x) => { let a = byFunc(x); if(res.hasOwnProperty(a)) res[a].push(x); else res[a] = [x]; }); return res; } export function array_grouping2(arr, byFunc, keyName = 'key', valueName = 'value') { let res = {}; let r = []; arr.forEach((x) => { let a = byFunc(x); if(res.hasOwnProperty(a)) res[a].push(x); else { let tmp = [x]; res[a] = tmp; let obj = {}; obj[keyName || 'key'] = a; obj[valueName || 'value'] = tmp; r.push(obj); } }); return r; } export function manual_page(list, page_no = 1, page_size = 10) { let start = (page_no - 1) * page_size; return list.slice(start, start + page_size); } export function array_toMap(arr, byFunc, overriding) { let res = {}; arr.forEach((x) => { let a = byFunc(x); if(!res.hasOwnProperty(a) || overriding) res[a] = x; }); return res; }