import { cloneDeep } from 'lodash' import moment from 'moment' import { FileType } from '@/enums/fileEnums' /** * @description 添加单位 * @param {String | Number} value 值 100 * @param {String} unit 单位 px em rem */ export const addUnit = (value: string | number, unit = 'px') => { return !Object.is(Number(value), NaN) ? `${value}${unit}` : value } /** * @description 添加单位 * @param {unknown} value * @return {Boolean} */ export const isEmpty = (value: unknown) => { return value == null && typeof value == 'undefined' } /** * @description 树转数组,队列实现广度优先遍历 * @param {Array} data 数据 * @param {Object} props `{ children: 'children' }` */ export const treeToArray = (data: any[], props = { children: 'children' }) => { data = cloneDeep(data) const { children } = props const newData = [] const queue: any[] = [] data.forEach((child: any) => queue.push(child)) while (queue.length) { const item: any = queue.shift() if (item[children]) { item[children].forEach((child: any) => queue.push(child)) delete item[children] } newData.push(item) } return newData } /** * @description 数组转 * @param {Array} data 数据 * @param {Object} props `{ parent: 'pid', children: 'children' }` */ export const arrayToTree = ( data: any[], props = { id: 'id', parentId: 'pid', children: 'children' } ) => { data = cloneDeep(data) const { id, parentId, children } = props const result: any[] = [] const map = new Map() data.forEach((item) => { map.set(item[id], item) const parent = map.get(item[parentId]) if (parent) { parent[children] = parent[children] ?? [] parent[children].push(item) } else { result.push(item) } }) return result } /** * @description 获取正确的路经 * @param {String} path 数据 */ export function getNormalPath(path: string) { if (path.length === 0 || !path || path == 'undefined') { return path } const newPath = path.replace('//', '/') const length = newPath.length if (newPath[length - 1] === '/') { return newPath.slice(0, length - 1) } return newPath } /** * @description 时间格式化 * @param dateTime { number } 时间戳 * @param fmt { string } 时间格式 * @return { string } */ // yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 export const timeFormat = (dateTime: number, fmt = 'yyyy-mm-dd') => { // 如果为null,则格式化当前时间 if (!dateTime) { dateTime = Number(new Date()) } // 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式 if (dateTime.toString().length == 10) { dateTime *= 1000 } const date = new Date(dateTime) let ret const opt: any = { 'y+': date.getFullYear().toString(), // 年 'm+': (date.getMonth() + 1).toString(), // 月 'd+': date.getDate().toString(), // 日 'h+': date.getHours().toString(), // 时 'M+': date.getMinutes().toString(), // 分 's+': date.getSeconds().toString() // 秒 } for (const k in opt) { ret = new RegExp('(' + k + ')').exec(fmt) if (ret) { fmt = fmt.replace( ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0') ) } } return fmt } export const timeDiffSeconds = (dateStr1: string, dateStr2: string, fmt: string) => { return moment(dateStr1, fmt).diff(moment(dateStr2, fmt), 'seconds') } /** * * @param seconds * @returns */ export const formatTimeText = (seconds: number) => { if (!seconds || seconds <= 0) { return '0' } // 秒 if (seconds < 60) { return seconds + '秒' } // 分钟 if (seconds < 3600) { return `${Math.floor(seconds / 60)}分${seconds % 60}秒` } // 小时 if (seconds < 86400) { const remainder = seconds % 3600; return `${Math.floor(seconds / 3600)}时${parseInt(seconds % 3600 / 60)}分` } // 天 const remainder = seconds % 86400; return `${Math.floor(seconds / 86400)}天${parseInt(seconds % 86400 / 3600)}时` } /** * @description 获取不重复的id * @param length { Number } id的长度 * @return { String } id */ export const getNonDuplicateID = (length = 8) => { let idStr = Date.now().toString(36) idStr += Math.random().toString(36).substring(3, length) return idStr } /** * @description 单词首字母大写 * @param { String } str * @return { String } id */ export const firstToUpperCase = (str = '') => { return str.toLowerCase().replace(/( |^)[a-z]/g, ($1) => $1.toUpperCase()) } export const getDictLable = (dictArr: any[], value: string) => { if (!value) { return '' } if (!dictArr || !dictArr.length) { return '' } const obj = dictArr.find(item => item.dictValue === value) if (!obj) { return '' } return obj.dictLabel; } export function getFlowTagType(flowName) { if (flowName === '待签收' || flowName === '待签收(协办)' || flowName === '信件退回' || flowName === '退回整改') { return 'danger' } if (flowName === '待下发' || flowName === '联系群众') { return 'warning' } if (flowName === '已办结') { return 'success' } return '' } /** * 验证身份证号码 * @param { String } code 身份证号码 */ export function validatorIdCard(rule: object, code: string, callback: any) { // 身份证号前两位代表区域 const city = { 11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江 ', 31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北 ', 43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏 ', 61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外 ', }; const idCardReg = /^[1-9]\d{5}(19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i; // 身份证格式正则表达式 // 如果身份证不满足格式正则表达式 if (!code) { return callback(new Error('请输入身份证号码')) } if (!code.match(idCardReg)) { return callback(new Error('请输入正确的身份证号码')) } if (!city[code.substr(0, 2)]) { // 区域数组中不包含需验证的身份证前两位 return callback(new Error('请输入正确的身份证号码')) } if (code.length === 18) { // 18位身份证需要验证最后一位校验位 code = code.split(''); // ∑(ai×Wi)(mod 11) // 加权因子 const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; // 校验位 const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]; let sum = 0; let ai = 0; let wi = 0; for (let i = 0; i < 17; i++) { ai = parseInt(code[i]); wi = factor[i]; sum += ai * wi; // 开始计算并相加 } const last = parity[sum % 11]; // 求余 if (last.toString() !== code[17]) { return callback(new Error('请输入正确的身份证号码')) } } callback() } /** * 校验手机号 * @param {*} phonenumber * @returns */ export function validatorPhone(rule: object, phonenumber: string, callback: any) { if (!phonenumber) { return callback(new Error('请输入手机号码')) } if (phonenumber.length !== 11) { return callback(new Error('请输入正确的手机号码')) } if (!/^1[3456789]\d{9}/.test(phonenumber)) { return callback(new Error('请输入正确的手机号码')) } callback() } export function getAppealType(appealState: String) { switch (appealState) { case '1': return 'primary' case '2': return 'success' case '3': return 'danger' default: break; } } export function getFileType(fileName) { if (!fileName) { return "unknown"; } fileName = fileName.toLocaleLowerCase(); if (fileName.endsWith('.pdf')) { return FileType.PDF; } if (fileName.endsWith('.jpg') || fileName.endsWith('.png') || fileName.endsWith('.gif')) { return FileType.IMG; } if (fileName.endsWith('.doc') || fileName.endsWith('.docx')) { return FileType.WORD; } if (fileName.endsWith('.xls') || fileName.endsWith('.xlsx')) { return FileType.EXCEL; } if (fileName.endsWith('.mp3') || fileName.endsWith('.m4a') || fileName.endsWith('.wav')) { return FileType.MP3; } if (fileName.endsWith('.mp4') || fileName.endsWith('.mpeg')) { return FileType.MP4; } return "unknown"; } export function getIconName(fileName) { const type = getFileType(fileName) if (type === FileType.PDF) { return 'local-icon-pdf' } if (type === FileType.IMG) { return "el-icon-Picture"; } if (type === FileType.WORD) { return "local-icon-doc"; } if (type === FileType.EXCEL) { return "local-icon-xls"; } if (type === FileType.MP3) { return "local-icon-mp3"; } if (type === FileType.MP4) { return "local-icon-mp4"; } return "el-icon-document"; } // 解析涉嫌问题 export function getInvolveProblem(json) { if (!json) { return '' } return JSON.parse(json).map(item => item.dictLabel).join(' ') } export function getGenderFromIdCode(idCode) { // 检查身份证号码是否有效(长度为18位) if (!idCode || idCode.length !== 18) { return ""; } // 获取第17位数字 const genderCode = parseInt(idCode.charAt(16), 10); // 检查是否为数字 if (isNaN(genderCode)) { return ""; } // 根据第17位数字判断性别 return genderCode % 2 === 0 ? "女" : "男"; }