521 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
		
			
		
	
	
			521 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			JavaScript
		
	
	
|  | import { ElMessage } from "element-plus"; | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 计算序号 | |||
|  |  * @param {Object} pagination 分页数据对象 | |||
|  |  * @param {number | string} pagination.currentPage 当前页 | |||
|  |  * @param {number | string} pagination.pageSize 每页条数 | |||
|  |  * @param {number} index 当页数据的索引值 | |||
|  |  * @return {number} 序号 | |||
|  |  **/ | |||
|  | export function serialNumber(pagination, index) { | |||
|  |   return (pagination.currentPage - 1) * pagination.pageSize + (index + 1); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 字符串数组转数组 | |||
|  |  * @param {string} value 转换的字符串数组 | |||
|  |  * @return {Array} 转换后的数组 | |||
|  |  **/ | |||
|  | export function toArrayString(value) { | |||
|  |   // eslint-disable-next-line no-eval
 | |||
|  |   return value ? eval(value).map(String) : []; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 判断文件后缀名是否符合 | |||
|  |  * @param {string} name 文件名字 | |||
|  |  * @param {string} suffix 文件后缀 | |||
|  |  * @return {boolean} 是否符合 | |||
|  |  **/ | |||
|  | export function interceptTheSuffix(name, suffix) { | |||
|  |   return ( | |||
|  |     name.substring(name.lastIndexOf("."), name.length).toLowerCase() === | |||
|  |     suffix.toLowerCase() | |||
|  |   ); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 图片转base64 | |||
|  |  * @param {string} imgUrl 图片地址 | |||
|  |  * @return {Promise} Promise实例,then包含base64编码 | |||
|  |  **/ | |||
|  | export function image2Base64(imgUrl) { | |||
|  |   return new Promise((resolve) => { | |||
|  |     const img = new Image(); | |||
|  |     img.src = imgUrl; | |||
|  |     img.crossOrigin = "Anonymous"; | |||
|  |     img.onload = function () { | |||
|  |       const canvas = document.createElement("canvas"); | |||
|  |       canvas.width = img.width; | |||
|  |       canvas.height = img.height; | |||
|  |       const ctx = canvas.getContext("2d"); | |||
|  |       ctx.drawImage(img, 0, 0, img.width, img.height); | |||
|  |       const ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase(); | |||
|  |       resolve(canvas.toDataURL("image/" + ext)); | |||
|  |     }; | |||
|  |   }); | |||
|  | } | |||
|  | export function image2Base642(file) { | |||
|  |   return new Promise((resolve, reject) => { | |||
|  |     const reader = new FileReader(); | |||
|  |     reader.readAsDataURL(file); | |||
|  |     reader.onload = (e) => { | |||
|  |       resolve(e.target.result); // 返回 base64
 | |||
|  |     }; | |||
|  |     reader.onerror = (error) => { | |||
|  |       reject(error); // 处理错误
 | |||
|  |     }; | |||
|  |   }); | |||
|  | } | |||
|  | /** | |||
|  |  * @description 判断图片是否可访问成功 | |||
|  |  * @param {string} imgUrl 图片地址 | |||
|  |  * @return {Promise} Promise实例 | |||
|  |  **/ | |||
|  | export function checkImgExists(imgUrl) { | |||
|  |   return new Promise((resolve, reject) => { | |||
|  |     const ImgObj = new Image(); | |||
|  |     ImgObj.src = imgUrl; | |||
|  |     ImgObj.onload = function (res) { | |||
|  |       resolve(res); | |||
|  |     }; | |||
|  |     ImgObj.onerror = function (err) { | |||
|  |       reject(err); | |||
|  |     }; | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取数据类型 | |||
|  |  * @param {any} data 数据 | |||
|  |  * @return {string} 数据类型 | |||
|  |  **/ | |||
|  | export function getDataType(data) { | |||
|  |   return Object.prototype.toString.call(data).slice(8, -1); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 数组去重 | |||
|  |  * @param {Array<number,string>} arr 去重的数组 | |||
|  |  * @return {Array} 去重后的数组 | |||
|  |  **/ | |||
|  | export function ArrayDeduplication(arr) { | |||
|  |   return [...new Set(arr)]; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 数组对象去重 | |||
|  |  * @param {Array} arr 去重的数组 | |||
|  |  * @param {string} name 去重的key | |||
|  |  * @return {Array} 去重后的数组 | |||
|  |  **/ | |||
|  | export function arrayObjectDeduplication(arr, name) { | |||
|  |   const obj = {}; | |||
|  |   arr = arr.reduce(function (previousValue, currentValue) { | |||
|  |     if (!obj[currentValue[name]]) { | |||
|  |       obj[currentValue[name]] = true; | |||
|  |       previousValue.push(currentValue); | |||
|  |     } | |||
|  |     return previousValue; | |||
|  |   }, []); | |||
|  |   return arr; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 查找字符串中指定的值第几次出现的位置 | |||
|  |  * @param {Array} str 查找的字符串数组 | |||
|  |  * @param {string} char 查找的值 | |||
|  |  * @param {number} num 第几次出现 | |||
|  |  * @return {number} 出现的位置 | |||
|  |  **/ | |||
|  | export function findCharIndex(str, char, num) { | |||
|  |   let index = str.indexOf(char); | |||
|  |   if (index === -1) return -1; | |||
|  |   for (let i = 0; i < num - 1; i++) { | |||
|  |     index = str.indexOf(char, index + 1); | |||
|  |     if (index === -1) return -1; | |||
|  |   } | |||
|  |   return index; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 生成指定两个值之间的随机数 | |||
|  |  * @param {number} min 最小值 | |||
|  |  * @param {number} max 最大值 | |||
|  |  * @return {number} 随机数 | |||
|  |  **/ | |||
|  | export function randoms(min, max) { | |||
|  |   return Math.random() * (max - min + 1) + min; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 千位分隔符 | |||
|  |  * @param {number | string} num 转换的值 | |||
|  |  * @return {string} 转换后的值 | |||
|  |  **/ | |||
|  | export function numFormat(num) { | |||
|  |   if (num) { | |||
|  |     const numArr = num.toString().split("."); | |||
|  |     const arr = numArr[0].split("").reverse(); | |||
|  |     let res = []; | |||
|  |     for (let i = 0; i < arr.length; i++) { | |||
|  |       if (i % 3 === 0 && i !== 0) { | |||
|  |         res.push(","); | |||
|  |       } | |||
|  |       res.push(arr[i]); | |||
|  |     } | |||
|  |     res.reverse(); | |||
|  |     if (numArr[1]) { | |||
|  |       res = res.join("").concat("." + numArr[1]); | |||
|  |     } else { | |||
|  |       res = res.join(""); | |||
|  |     } | |||
|  |     return res; | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 验证是否为空 | |||
|  |  * @param {any} value 验证的值 | |||
|  |  * @return {boolean} 是否为空 | |||
|  |  **/ | |||
|  | export function isEmpty(value) { | |||
|  |   return ( | |||
|  |     value === undefined || | |||
|  |     value === null || | |||
|  |     (typeof value === "object" && Object.keys(value).length === 0) || | |||
|  |     (typeof value === "string" && value.trim().length === 0) | |||
|  |   ); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取url参数 | |||
|  |  * @param {string} name 获取的key | |||
|  |  * @return {string} 获取的值 | |||
|  |  **/ | |||
|  | export function getUrlParam(name) { | |||
|  |   const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); | |||
|  |   const r = window.location.search.substr(1).match(reg); | |||
|  |   if (r != null) return decodeURI(r[2]); | |||
|  |   return ""; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 数据分页 | |||
|  |  * @param {Array} list 分页的数组 | |||
|  |  * @param {number | string} currentPage 当前页 | |||
|  |  * @param {number | string} pageSize 每页条数 | |||
|  |  * @return {Array} 分页后的数组 | |||
|  |  **/ | |||
|  | export function paging(list, currentPage, pageSize) { | |||
|  |   return list.filter((item, index) => { | |||
|  |     return ( | |||
|  |       index < +currentPage * +pageSize && | |||
|  |       index >= (+currentPage - 1) * +pageSize | |||
|  |     ); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取文件后缀 | |||
|  |  * @param {string} name 文件名 | |||
|  |  * @return {string} 文件后缀 | |||
|  |  **/ | |||
|  | export function getFileSuffix(name) { | |||
|  |   return name.substring(name.lastIndexOf(".") + 1); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取文件名称 | |||
|  |  * @param {string} name 文件地址 | |||
|  |  * @return {string} 文件名称 | |||
|  |  **/ | |||
|  | export function getFileName(name) { | |||
|  |   if (!name) return ""; | |||
|  |   return name.substring(name.lastIndexOf("/") + 1); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 读取txt文档 | |||
|  |  * @param {string} filePah 文档路径 | |||
|  |  * @return {resolve,string} 读取后的内容 | |||
|  |  **/ | |||
|  | export function readTxtDocument(filePah) { | |||
|  |   return new Promise((resolve) => { | |||
|  |     const FILE_URL = getFileUrl(); | |||
|  |     const file_url = FILE_URL + filePah; | |||
|  |     const xhr = new XMLHttpRequest(); | |||
|  |     xhr.open("get", file_url, true); | |||
|  |     xhr.responseType = "blob"; | |||
|  |     xhr.onload = function (event) { | |||
|  |       const reader = new FileReader(); | |||
|  |       reader.readAsText(event.target.response, "GB2312"); | |||
|  |       reader.onload = function () { | |||
|  |         resolve(reader.result); | |||
|  |       }; | |||
|  |     }; | |||
|  |     xhr.send(); | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 将秒转换成时分秒 | |||
|  |  * @param {string,number} second 需要转换的秒数 | |||
|  |  * @return {string} 转换后的时间 | |||
|  |  **/ | |||
|  | export function secondConversion(second) { | |||
|  |   if (!second) return 0; | |||
|  |   const h = parseInt(second / 60 / 60, 10); | |||
|  |   const m = parseInt((second / 60) % 60, 10); | |||
|  |   const s = parseInt(second % 60, 10); | |||
|  |   if (h) { | |||
|  |     return h + "小时" + m + "分钟" + s + "秒"; | |||
|  |   } else { | |||
|  |     if (m) { | |||
|  |       return m + "分钟" + s + "秒"; | |||
|  |     } else { | |||
|  |       return s + "秒"; | |||
|  |     } | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 附件添加前缀 | |||
|  |  * @param {Array} list 附件数组 | |||
|  |  * @param {Object} options 配置选项 | |||
|  |  * @param {string} [options.pathKey="filePath"] 附件路径字段名 | |||
|  |  * @param {string} [options.nameKey="fileName"] 附件名称字段名 | |||
|  |  * @param {string} [options.idKey="imgFilesId"] 附件id字段名 | |||
|  |  * @return {Array} 添加完前缀后的数组 | |||
|  |  **/ | |||
|  | export function addingPrefixToFile(list, options = {}) { | |||
|  |   if (!list) return []; | |||
|  |   const { | |||
|  |     pathKey = "filePath", | |||
|  |     nameKey = "fileName", | |||
|  |     idKey = "imgFilesId", | |||
|  |   } = options; | |||
|  |   const FILE_URL = getFileUrl(); | |||
|  |   for (let i = 0; i < list.length; i++) { | |||
|  |     list[i].url = FILE_URL + list[i][pathKey]; | |||
|  |     list[i].name = list[i][nameKey] || getFileName(list[i][pathKey]); | |||
|  |     list[i].imgFilesId = list[i][idKey]; | |||
|  |   } | |||
|  |   return list; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 验证重复选择 | |||
|  |  * @param {Array} list 验证的数组 | |||
|  |  * @param {number} index 选择的索引 | |||
|  |  * @param {string} key 验证的字段 | |||
|  |  * @param {string} id 验证的值 | |||
|  |  **/ | |||
|  | export async function verifyDuplicateSelection(list, index, key, id) { | |||
|  |   return new Promise((resolve, reject) => { | |||
|  |     if (list.some((item) => item[key] === id)) { | |||
|  |       ElMessage.warning("不能重复选择"); | |||
|  |       reject(new Error("不能重复选择")); | |||
|  |     } else { | |||
|  |       list[index][key] = id; | |||
|  |       resolve(); | |||
|  |     } | |||
|  |   }); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 翻译状态 | |||
|  |  * @param {number | string} status 状态 | |||
|  |  * @param {Array} list 翻译的数组 | |||
|  |  * @param {String} idKey | |||
|  |  * @param {String} nameKey | |||
|  |  * @return {string} 翻译后的状态 | |||
|  |  **/ | |||
|  | export function getLabelName(status, list, idKey = "id", nameKey = "name") { | |||
|  |   for (let i = 0; i < list.length; i++) { | |||
|  |     if (status?.toString() === list[i][idKey]?.toString()) { | |||
|  |       return list[i][nameKey]; | |||
|  |     } | |||
|  |   } | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 计算文件大小 | |||
|  |  * @param {number | string} size 文件kb | |||
|  |  * @return {string} 计算后的文件大小 | |||
|  |  **/ | |||
|  | export function calculateFileSize(size) { | |||
|  |   return size > 1024 | |||
|  |     ? (size / 1024 + "").substring(0, (size / 1024 + "").lastIndexOf(".") + 3) + | |||
|  |         "MB" | |||
|  |     : size + "KB"; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 根据身份证号获取出生日期和性别 | |||
|  |  * @param {String} idCard 身份证号 | |||
|  |  * @return {Object} 出生日期和性别 date sex | |||
|  |  **/ | |||
|  | export function idCardGetDateAndGender(idCard) { | |||
|  |   const reg = | |||
|  |     /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/; | |||
|  |   let sex = ""; | |||
|  |   let date = ""; | |||
|  |   if (reg.test(idCard)) { | |||
|  |     const org_birthday = idCard.substring(6, 14); | |||
|  |     const org_gender = idCard.substring(16, 17); | |||
|  |     const birthday = | |||
|  |       org_birthday.substring(0, 4) + | |||
|  |       "-" + | |||
|  |       org_birthday.substring(4, 6) + | |||
|  |       "-" + | |||
|  |       org_birthday.substring(6, 8); | |||
|  |     const birthdays = new Date(birthday.replace(/-/g, "/")); | |||
|  |     const Month = birthdays.getMonth() + 1; | |||
|  |     let MonthDate; | |||
|  |     const DayDate = birthdays.getDate(); | |||
|  |     let Day; | |||
|  |     if (Month < 10) MonthDate = "0" + Month; | |||
|  |     else MonthDate = Month; | |||
|  |     if (DayDate < 10) Day = "0" + DayDate; | |||
|  |     else Day = DayDate; | |||
|  |     sex = org_gender % 2 === 1 ? "1" : "0"; | |||
|  |     date = birthdays.getFullYear() + "-" + MonthDate + "-" + Day; | |||
|  |   } | |||
|  |   return { sex, date }; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取select中指定项组成的数组 | |||
|  |  * @param {Array} list 获取的数组 | |||
|  |  * @param {Array} value 获取的值 | |||
|  |  * @param {string?} idKey 获取的id | |||
|  |  * @return {Array} list中指定项组成的数组 | |||
|  |  **/ | |||
|  | export function getSelectAppointItemList(list, value, idKey = "id") { | |||
|  |   return list.filter((item) => value.includes(item[idKey])); | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description json转换为树形结构 | |||
|  |  * @param {Array} json 需要转换的json | |||
|  |  * @param {string} idStr id字段 | |||
|  |  * @param {string} pidStr 父级id字段 | |||
|  |  * @param {string} childrenStr 子级字段 | |||
|  |  * @return {Array} 转换完的树形结构 | |||
|  |  **/ | |||
|  | export function listTransTree(json, idStr, pidStr, childrenStr) { | |||
|  |   const r = []; | |||
|  |   const hash = {}; | |||
|  |   const id = idStr; | |||
|  |   const pid = pidStr; | |||
|  |   const children = childrenStr; | |||
|  |   let i = 0; | |||
|  |   let j = 0; | |||
|  |   const len = json.length; | |||
|  |   for (; i < len; i++) { | |||
|  |     hash[json[i][id]] = json[i]; | |||
|  |   } | |||
|  |   for (; j < len; j++) { | |||
|  |     const aVal = json[j]; | |||
|  |     const hashVP = hash[aVal[pid]]; | |||
|  |     if (hashVP) { | |||
|  |       !hashVP[children] && (hashVP[children] = []); | |||
|  |       hashVP[children].push(aVal); | |||
|  |     } else { | |||
|  |       r.push(aVal); | |||
|  |     } | |||
|  |   } | |||
|  |   return r; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 将值转换为"是"/"否"显示文本 | |||
|  |  * @param {any} value 需要转换的值 | |||
|  |  * @param {Object} options 配置选项 | |||
|  |  * @param {string} options.yesText 真值时显示的文本,默认为"是" | |||
|  |  * @param {string} options.noText 假值时显示的文本,默认为"否" | |||
|  |  * @param {string|number} options.yesValue 判断为真的值,默认为"1" | |||
|  |  * @return {string} 转换后的显示文本 | |||
|  |  **/ | |||
|  | export function isEmptyToWhether(value, options = {}) { | |||
|  |   const { yesText = "是", noText = "否", yesValue = "1" } = options; | |||
|  |   return !isEmpty(value) | |||
|  |     ? value.toString() === yesValue.toString() | |||
|  |       ? yesText | |||
|  |       : noText | |||
|  |     : ""; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 计算表格中需要合并的行信息 | |||
|  |  * @param {Array} data 表格数据数组 | |||
|  |  * @param {string} field 用于比较的字段名,相同值的行需要合并 | |||
|  |  * @param {Number} rowIndex 当前行索引 | |||
|  |  * @returns {Object} 包含rowspan和colspan属性的对象,用于表格单元格合并 | |||
|  |  *  - rowspan {number} 合并行数 | |||
|  |  *  - colspan {number} 合并列数 | |||
|  |  */ | |||
|  | 
 | |||
|  | export function getRowSpans(data, field, rowIndex) { | |||
|  |   if (!Array.isArray(data) || data.length === 0 || rowIndex < 0) { | |||
|  |     return { rowspan: 1, colspan: 1 }; | |||
|  |   } | |||
|  |   if (data.length === 1) { | |||
|  |     return { rowspan: 1, colspan: 1 }; | |||
|  |   } | |||
|  |   let currentSpanCount = 1; | |||
|  |   let currentSpanIndex = 0; | |||
|  |   for (let i = 1; i < data.length; i++) { | |||
|  |     const currentValue = data[i][field]; | |||
|  |     const previousValue = data[i - 1][field]; | |||
|  |     if (currentValue === previousValue) { | |||
|  |       currentSpanCount++; | |||
|  |       if (i === rowIndex) { | |||
|  |         return { rowspan: 0, colspan: 0 }; | |||
|  |       } | |||
|  |     } else { | |||
|  |       if (currentSpanIndex === rowIndex) { | |||
|  |         return { rowspan: currentSpanCount, colspan: 1 }; | |||
|  |       } | |||
|  |       currentSpanIndex = i; | |||
|  |       currentSpanCount = 1; | |||
|  |     } | |||
|  |   } | |||
|  |   if (currentSpanIndex === rowIndex) { | |||
|  |     return { rowspan: currentSpanCount, colspan: 1 }; | |||
|  |   } | |||
|  |   return { rowspan: 1, colspan: 1 }; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 生成指定长度的guid | |||
|  |  * @param {number} len 生成的guid长度 | |||
|  |  * @return {string} 生成的guid | |||
|  |  **/ | |||
|  | export function createGuid(len = 32) { | |||
|  |   const chars = "abcdefghijklmnopqrstuvwxyz0123456789"; | |||
|  |   let result = ""; | |||
|  |   for (let i = 0; i < len; i++) { | |||
|  |     result += chars.charAt(Math.floor(Math.random() * chars.length)); | |||
|  |   } | |||
|  |   return result; | |||
|  | } | |||
|  | 
 | |||
|  | /** | |||
|  |  * @description 获取文件路径前缀地址 | |||
|  |  * @return {string} 文件路径前缀地址 | |||
|  |  **/ | |||
|  | export function getFileUrl() { | |||
|  |   return import.meta.env.VITE_FILE_URL; | |||
|  | } | |||
|  | 
 | |||
|  | export function getBaseUrl() { | |||
|  |   return import.meta.env[import.meta.env.DEV ? "VITE_PROXY" : "VITE_BASE_URL"]; | |||
|  | } | |||
|  | 
 | |||
|  | export function getWebUrl() { | |||
|  |   return window.location.origin + window.location.pathname + "#"; | |||
|  | } |