// 引入导出Excel表格依赖 import * as FileSaver from "file-saver" import * as XLSX from "xlsx" import { getItem } from "@/utils/storage" import { getApi, postApi } from "@/api/tobAcco_api.js" import store from "@/store" import { ElLoading } from "element-plus" // 获取图片访问路径 export const getImgUrl = iconName => { if (process.env.NODE_ENV === "development") { return "http://192.168.1.6:8888/" + iconName } else if (process.env.NODE_ENV === "production") { return window.location.origin + "/files/" + iconName//云平台 } } //是否是字符串类型 export function isString(value) { return typeof value === "string" } //生成uuid export function generateUUID() { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { var r = (Math.random() * 16) | 0, v = c === "x" ? r : (r & 0x3) | 0x8 return v.toString(16) }) } // 下载模板,携带token export function downloadTemplate(type, fileName) { fileName = fileName ? fileName : "模板" let url = `/mosty-api/mosty-jcgl/common/exportExcelTemplate?type=${type}` let token = getItem("token") const headers = new Headers() headers.append("Authorization", token) // 设置token // 发起 Fetch 请求 fetch(url, { method: "GET", headers: headers }) .then(res => res.blob()) .then(blob => { let a = document.createElement("a") a.download = fileName + ".xlsx" a.href = window.URL.createObjectURL(blob) a.style.display = "none" document.body.appendChild(a) a.click() a.remove() }) .catch(error => console.error("下载失败:", error)) } // 下载模板,携带token export function downloadewm(url, fileName) { const loading = ElLoading.service({ lock: true, text: "下载中...", background: "rgba(0, 0, 0, 0.7)" }) fileName = fileName ? fileName : "" let token = getItem("token") const headers = new Headers() headers.append("Authorization", token) // 设置token // 发起 Fetch 请求 fetch(url, { method: "GET", headers: headers }) .then(res => res.blob()) .then(blob => { let a = document.createElement("a") a.download = fileName + ".zip" a.href = window.URL.createObjectURL(blob) a.style.display = "none" document.body.appendChild(a) a.click() a.remove() loading.close() }) .catch(error => { loading.close() console.error("下载失败:", error) } ) } // 下载二维码 export function qrcodeImg(id, type, ...name) { let url = `/mosty-api/mosty-jcgl/common/createQrCode?objid=${id}&type=${type}` if (name.length > 0) { for (let i = 0; i < name.length; i++) { const el = name[i] url = url + `&texts=${el}` } } return url } //下载培训二维码 export function qrcodepxImg(id, type, name, ...texts) { let url = `/mosty-api/mosty-jcgl/common/createQrCodeNoStyle?objid=${id}&objname=${name}&type=${type}` if (texts.length > 0) { for (let i = 0; i < texts.length; i++) { const el = texts[i] url = url + `&texts=${el}` } } return url } /** * 数据去重 相同数据值累加 * @param {Object} array 数据 */ export function setArray(array) { let newArr = [] array.forEach(item => { const res = newArr.findIndex(ol => { //组织机构代码相同 并且报警类别相同 return item.ssbmdm == ol.ssbmdm && item.bjlb == ol.bjlb }) if (res !== -1) { newArr[res].sl = newArr[res].sl + item.sl } else { newArr.push(item) } }) return newArr } /** * 合并数据 * @param {Object} array 数据 */ export function hbArray(array, item1, item2, item3) { let newArr = [] array.forEach(item => { const res = newArr.findIndex(ol => { //组织机构代码相同 并且报警类别相同 return item.product == ol.product }) if (res !== -1) { newArr[res][item1] = newArr[res][item1] + item[item1] newArr[res][item2] = newArr[res][item2] + item[item2] newArr[res][item3] = newArr[res][item3] + item[item3] } else { newArr.push(item) } }) return newArr } /** *时间格式 * @export * @param {*} [obj={}] type:时间类型 time:时间 * @return {*} 返回的时间 */ export function dateFormat(obj = {}) { let { type, time } = obj let date if (time) { date = new Date(time) } else { date = new Date() } let year = date.getFullYear() let month = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1 let hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours() let minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes() let seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds() let day if (type == "front_one_day") { //前一天日期 day = date.getDate() - 1 day = day < 10 ? "0" + day : day return `${year}-${month}-${day}` } else if (type == "month") { // month = month < 10 ? "0" + month : month; //返回年月 return `${year}-${month}` } else if (type == "one") { //返回当年一月 month = date.getMonth() - date.getMonth() + 1 month = month < 10 ? "0" + month : month return `${year}-${month}` } else if (type == "all") { //格式化日期时间 day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate() return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } else if (type == "queen_two_hour") { //后两小时 let date1 = new Date(date.getTime() + 2 * 60 * 60 * 1000) return setTimeTormat(date1) } else if (type == "year") { //返回年份 return year } else if (type == "sfm") { //返回年份 let hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours() let minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes() let seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds() return `${hours}:${minutes}:${seconds}` } else if (type == "day") { day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate() // month = month < 10 ? "0" + month : month; //返回年月日 return `${year}-${month}-${day}` } else if (type == "ones") { //返回当年一月 month = date.getMonth() - date.getMonth() + 1 month = month < 10 ? "0" + month : month day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate() return `${year}-${month}-${day}` } else if (type == "lastmonth") { // 计算上一个月的年份和月份 date.setMonth(date.getMonth() - 1) let months = date.getMonth() + 1 if (months < 10) { months = "0" + (date.getMonth() + 1) } return `${date.getFullYear()}-${months}` } else if (type == "firstday") { // 获取当年第一天 return `${year}-01-01` } else { //当天日期 day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate() return `${year}-${month}-${day}` } } // 累加或者累减保持精度 /** * * @param {*String} type 默认add加 * @param {*Number} part 保留几位小数 4 * @param {...any} args 需要加减的参数 * @param {Number} total 初始值 * @returns */ export function numAdd(type = "add", part = 4, total = 0, ...args) { let count = Number(total) for (let i = 0; i < args.length; i++) { if (isNaN(args[i])) { continue } else { args[i] = Number(args[i]) count = type == "add" ? (count += args[i]) : (count -= args[i]) } } return part != -1 ? Number(count.toPrecision(20)).toFixed(part) : Number(count.toPrecision(20)) } //设置时间 function setTimeTormat(date) { let year1 = date.getFullYear() let month1 = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1 let day1 = date.getDate() < 10 ? "0" + date.getDate() : date.getDate() let hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours() let minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes() let seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds() return `${year1}-${month1}-${day1} ${hours}:${minutes}:${seconds}` } /** * 查询当天日期 */ export function getNowDate() { const timeOne = new Date() const year = timeOne.getFullYear() let month = timeOne.getMonth() + 1 let day = timeOne.getDate() month = month < 10 ? "0" + month : month day = day < 10 ? "0" + day : day const NOW_MONTHS_AGO = `${year}.${month}.${day}` return NOW_MONTHS_AGO } // 获取当前系统的时间 export function formatTime(data, flag) { const date = data ? new Date(data) : new Date() const y = date.getFullYear() let m = date.getMonth() + 1 m = m < 10 ? "0" + m : m let d = date.getDate() d = d < 10 ? "0" + d : d let h = date.getHours() h = h < 10 ? "0" + h : h let minute = date.getMinutes() minute = minute < 10 ? "0" + minute : minute let second = date.getSeconds() second = second < 10 ? "0" + second : second if (flag == "ymd") { return y + "-" + m + "-" + d } else if (flag == "ym") { return y + "-" + m } else { return h + ":" + minute + ":" + second } } //选择出生日期 export function getDefaultDate() { const now = new Date() const oneYearAgo = new Date(now.getFullYear() - 18, now.getMonth(), now.getDate()) return oneYearAgo.toISOString().substring(0, 10) } //禁止选择18年后的日期 export function disabledDate(time) { const date = new Date(time) const year = date.getFullYear() return year > new Date().getFullYear() - 18 } //禁止选择当前系统之前的时间以及当前系统日期 export function disablednowDate(time) { return time.getTime() + 24 * 60 * 60 * 1000 > Date.now() } export function disablednowDate1(time) { return time.getTime() > Date.now() } //禁止选择当前系统之后的时间 export function disablednowDates(time) { return time.getTime() + 24 * 60 * 60 * 1000 < Date.now() } //禁止选择当前系统之后的月份 export function disablednowmonth(time) { return time.getTime() < Date.now() } //数字超长处理 export function handleNum(num) { var data = 0 if (num) { try { if (num * 1 > 100000) { data = (num / 10000).toFixed(0) + "万" } else { data = (num * 1).toFixed(0) } } catch (error) { data = 0 } } return data } /** * 文件是否是图片 * @param {*} val */ export function IS_PNG(val) { return ( ["bmp", "jpg", "png", "tif", "gif", "pcx", "tga", "exif", "fpx", "svg", "psd", "cdr", "pcd", "dxf", "ufo", "eps", "ai", "raw", "wmf", "webp", "avif", "apng"].indexOf( val.toLowerCase() ) !== -1 ) } /** * 文件是否是音频 * @param {*} val */ export function IS_MP3(val) { return ["mp3", "wav", "wma", "mp2", "flac", "midi", "ra", "ape", "aac", "cda", "mov"].indexOf(val.toLowerCase()) !== -1 } /** * 文件是否是视频 * @param {*} val */ export function IS_MP4(val) { return ["avi", "wmv", "mpeg", "mp4", "m4v", "mov", "asf", "fiv", "f4v", "mvb", "rm", "3gp", "vob"].indexOf(val.toLowerCase()) !== -1 } /** *对象数组排序 * @export * @param {*} attr 排序的字段 * @param {*} rev true 升序 false 降序 */ export function compare(attr, rev) { if (rev == undefined) { rev = 1 } else { rev = rev ? 1 : -1 } return (a, b) => { a = a[attr] b = b[attr] if (a > b) { return rev * -1 } if (a < b) { return rev * 1 } return 0 } } //附件下载 export function createAndClickLink(downloadUrl, fileName) { return new Promise((resolve, reject) => { const xhr = new window.XMLHttpRequest() xhr.open("GET", downloadUrl, true) xhr.responseType = "blob" xhr.onload = () => { const url = window.URL.createObjectURL(xhr.response) const a = document.createElement("a") a.href = url a.download = fileName // 使用 setTimeout 延迟点击操作 setTimeout(() => { a.click() window.URL.revokeObjectURL(url) // 释放资源 resolve() // 解决 Promise }, 0) } xhr.onerror = () => { reject(new Error("文件下载失败")) } xhr.send() }) } /** *导出表格 * @export * @param {object} title 表头 * @param {Array} data 数据 * @param {*} XLSX 插件实例化对象 * @param {*} fileName 文件名称 */ export function exportXlsx(title, tableData, XLSX, fileName) { const list = tableData.map(item => { const obj = {} for (const k in item) { if (title[k]) { obj[title[k]] = item[k] } } return obj }) //创建表个数据 const data = XLSX.utils.json_to_sheet(list) const wb = XLSX.utils.book_new() XLSX.utils.book_append_sheet(wb, data, "data") XLSX.writeFile(wb, fileName + ".xlsx") } //节流 export function _throttle(func, delay) { let timer = null let startTime = Date.now() return () => { let curTime = Date.now() let remaining = delay - (curTime - startTime) let context = this let args = arguments clearTimeout(timer) if (remaining <= 0) { func.apply(context, args) startTime = Date.now() } else { timer = setTimeout(func, remaining) } } } //echarts自适应 export function chartAdaptation(chart) { const DELAY = 500 // 延迟时间 let fnn = _throttle(() => { setTimeout(() => { chart.resize() }, 300) }, DELAY) window.addEventListener("resize", fnn) } //深拷贝 export function deepClone(obj, cache = new WeakMap()) { if (typeof obj !== "object") return obj // 普通类型,直接返回 if (obj === null) return obj if (cache.get(obj)) return cache.get(obj) // 防止循环引用,程序进入死循环 if (obj instanceof Date) return new Date(obj) if (obj instanceof RegExp) return new RegExp(obj) // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数 let cloneObj = new obj.constructor() cache.set(obj, cloneObj) // 缓存拷贝的对象,用于处理循环引用的情况 for (let key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { cloneObj[key] = deepClone(obj[key], cache) // 递归拷贝 } } return cloneObj } //导出为Excel表格 exportExcel export function exportExcel(tabname) { //从表生成工作簿对象 var wb = XLSX.utils.table_to_book(document.querySelector("#out-table")) //获取二进制字符串作为输出 var wbout = XLSX.write(wb, { bookType: "xlsx", bookSST: true, type: "array" }) try { FileSaver.saveAs( //Blob 对象表示一个不可变、原始数据的类文件对象。 //Blob 表示的不一定是JavaScript原生格式的数据。 //File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。 //返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成。 new Blob([wbout], { type: "application/octet-stream" }), //设置导出文件名称 `${tabname ? tabname : "index"}.xlsx` ) } catch (e) { if (typeof console !== "undefined") { } } return wbout } //表格合计 export function getSummaries(param) { const { columns, data } = param const sums = [] columns.forEach((column, index) => { if (index === 0) { sums[index] = "合计" return } const values = data.map(item => Number(item[column.property])) if (!values.every(value => isNaN(value))) { sums[index] = values.reduce((prev, curr) => { const value = Number(curr) if (!isNaN(value)) { return numAdd("add", -1, prev, curr) } else { return prev } }, 0) } else { sums[index] = "N/A" } }) return sums } //合并数组方法 export function mergeArray(arr1, arr2) { const newArray = [] let length1 = arr1.length let length2 = arr2.length for (let i = 0; i < length1; i++) { for (let j = 0; j < length2; j++) { if (i == j) { let mergeItem = Object.assign(arr1[i], arr2[j]) newArray.push(mergeItem) break } } } return newArray } /* 1 . 手机校验 */ export const validatePhone = rule => { return (rule, value, callback) => { if (!value) { } else { const reg = /^1[3|4|5|7|8][0-9]\d{8}$/ if (reg.test(value)) { callback() } else { return callback(new Error("请输入正确的手机号")) } } } } //身份证校验 export const validateIdentity = () => { return (rule, value, callback) => { if (!value) { // return callback(new Error('身份证号不能为空')); } else if (!/(^\d{15}$)|(^\d{17}(\d|X|x)$)/.test(value)) { callback(new Error("输入的身份证长度或格式错误")) } //身份证城市 var aCity = { 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: "国外" } if (!aCity[parseInt(value.substr(0, 2))]) { callback(new Error("身份证地区非法")) } // 出生日期验证 var sBirthday = (value.substr(6, 4) + "-" + Number(value.substr(10, 2)) + "-" + Number(value.substr(12, 2))).replace(/-/g, "/"), d = new Date(sBirthday) if (sBirthday !== d.getFullYear() + "/" + (d.getMonth() + 1) + "/" + d.getDate()) { callback(new Error("身份证上的出生日期非法")) } // 身份证号码校验 var sum = 0, weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2], codes = "10X98765432" for (var i = 0; i < value.length - 1; i++) { sum += value[i] * weights[i] } var last = codes[sum % 11] //计算出来的最后一位身份证号码 if (value[value.length - 1] !== last) { callback(new Error("输入的身份证号非法")) } callback() } } /** * 根据身份证计算出生日期 * @param {*} idCard * @returns */ export function getBirthdayFromIdCard(idCard) { var birthday = "" if (idCard != null && idCard != "") { if (idCard.length == 15) { birthday = "19" + idCard.substr(6, 6) } else if (idCard.length == 18) { birthday = idCard.substr(6, 8) } birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-") } return birthday } /** * 倒计时 * @param {*} time 目标时间 * @returns */ export function countDown(time) { // 设置目标时间,这里以毫秒为单位。例如,设置为当前时间后的1小时 let countDownDate = time ? new Date(time).getTime() : new Date().getTime() // 1小时后的时间 // 获取当前时间 let now = new Date().getTime() // 计算距离时间 let distance = countDownDate - now // 倒计时时间计算 let num, obj = { overtime: false, timeValue: "" } if (distance > 0) { num = distance } else { // 如果倒计时结束 num = Math.floor(Math.abs(distance)) obj.overtime = true } let days = Math.floor(num / (1000 * 60 * 60 * 24)) let hours = Math.floor((num % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)) let minutes = Math.floor((num % (1000 * 60 * 60)) / (1000 * 60)) let seconds = Math.floor((num % (1000 * 60)) / 1000) obj.timeValue = days + "天 " + hours + "时 " + minutes + "分 " + seconds + "秒 " return obj } export function weekValidate(date) { let val = (new Date(date)).getDay() switch (val) { case 0: return "星期日" case 1: return "星期一" case 2: return "星期二" case 3: return "星期三" case 4: return "星期四" case 5: return "星期五" case 6: return "星期六" } } // 转换时间格式 export function timeValidate(date, type) { const time = date ? new Date(date) : new Date() const yyyy = time.getFullYear() const MM = (time.getMonth() + 1).toString().padStart(2, 0) const dd = time.getDate().toString().padStart(2, "0") const hh = time.getHours().toString().padStart(2, "0") const mm = time.getMinutes().toString().padStart(2, "0") const ss = time.getSeconds().toString().padStart(2, "0") if (type == "ymd") { return `${yyyy}-${MM}-${dd}` } if (type == "md") { return `${MM}.${dd}` } return `${yyyy}-${MM}-${dd} ${hh}:${mm}:${ss}` } /**根据字典获取值 * @param {Array} dicArr 字典数组 * @param {String} val 值 */ export function getValByDic(val, dicArr) { val = typeof val === "string" ? val : "" /** 是否多个数值 */ const isMult = val.indexOf(",") > -1 if (val === undefined) return "" dicArr = Array.isArray(dicArr) ? dicArr : [] /** 字典对象 */ let dicObj = {} for (let i = 0; i < dicArr.length; i++) { const item = dicArr[i] dicObj[item.value] = item.label } if (isMult) { let valArr = val.split(",") return valArr.map(dm => dicObj[dm]).join(",") } else { return dicObj[val] || val || "" // 查询不到返回原值 } } /** 按钮权限 */ export function getAuth() { return new Promise((resolve, reject) => { // 先强制为 true TODO: 方便所有人有权限 resolve(true) // 后面以后用 // getApi({}, '/mosty-jcgl/securitychild/isAqyPower').then(res => { // store.dispatch('user/setAuth', res) // resolve(res) // }) }) } /** * 限制小数位数 * @param { Number,String} 值 * @param {Number} num 小数位数 */ export function numberLimit(val, num = 2) { if (val === 0) return "0" if (!val) return "" if (typeof val === "number") val = String(val) if (typeof val !== "string") return "" switch (num) { case 1: return val.match(/\d+\.?\d{0,1}/)?.[0] || "" break case 2: return val.match(/\d+\.?\d{0,2}/)?.[0] || "" break case 3: return val.match(/\d+\.?\d{0,3}/)?.[0] || "" break case 4: return val.match(/\d+\.?\d{0,4}/)?.[0] || "" break } return "" } /** * 将数字转换为中文数字表示形式 如11: 十一 * * @param {number} num - 要转换的数字。 * @returns {string} - 转换后的中文数字字符串。 */ export function toChineseNumber(num) { // 四位四位的进行分割 const parts = num .toString() .replace(/(?=(\d{4})+$)/g, ",") .split(",") .filter(Boolean) const map = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"] const units = ["", "十", "百", "千"] // 把连续的零给去掉 合并为1个零 当零在末尾的时候去掉 function _handleZero(str) { return str.replace(/零+/g, "零").replace(/零$/, "") } function _transform(n) { let result = "" for (let i = 0; i < n.length; i++) { const c = map[n[i]] let u = units[n.length - i - 1] if (c === "零") { u = "" } result += c + u } result = _handleZero(result) return result } const bigUnits = ["", "万", "亿"] let result = "" for (let i = 0; i < parts.length; i++) { const p = parts[i] const c = _transform(p) const u = bigUnits[parts.length - i - 1] if (c === "") { result += "零" continue } result += c + u } result = _handleZero(result) if (result === "一十一") return "十一" if (result === "一十二") return "十二" if (result === "一十三") return "十三" if (result === "一十四") return "十四" if (result === "一十五") return "十五" if (result === "一十六") return "十六" if (result === "一十七") return "十七" if (result === "一十八") return "十八" if (result === "一十九") return "十九" return result } /** * 从一个列表中过滤目标数组 * @param originalData * @param filteredData */ export const arrayFiltering = (originalData, filteredData) => { let data = originalData for (let i = 0; i < data.length; i++) { for (let j = 0; j < filteredData.length; j++) { if (filteredData[j] in data[i]) { if (typeof data[i][filteredData[j]] !== "number" && typeof data[i][filteredData[j]] !== "boolean") { if (data[i][filteredData[j]] !== null && (typeof data[i][filteredData[j]] === "string" || data[i][filteredData[j]] instanceof Array) && data[i][filteredData[j]].length) { if (j === filteredData.length - 1) { data[i]["sign"] = true } }else { data[i]["sign"] = false break } } } else { data[i]["sign"] = false break } } } return data } /** * 检查原始对象中是否包含合规的数据 * @param primaryObject * @param filterArray */ export const singleObjectCheck = (primaryObject, filterArray) => { for (let i = 0; i < filterArray.length; i++) { if (filterArray[i] in primaryObject) { if (typeof primaryObject[filterArray[i]] !== "number" && typeof primaryObject[filterArray[i]] !== "boolean" && typeof primaryObject[filterArray[i]] !== "undefined") { if (primaryObject[filterArray[i]] !== null && (typeof primaryObject[filterArray[i]] === "string" || primaryObject[filterArray[i]] instanceof Array) && primaryObject[filterArray[i]].length) { if (i === filterArray.length - 1) { primaryObject["sign"] = true } }else { primaryObject["sign"] = false break } }else { primaryObject["sign"] = true } } else { primaryObject["sign"] = false break } } return primaryObject } /** * 判断两个数组是否有交集 * @param arr1 * @param arr2 * @returns {boolean} */ export const haveIntersection = (arr1, arr2) => { return arr1.filter(item => arr2.includes(item)).length > 0; }