utils.ts 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /**
  2. * 判断对象类型
  3. * @param {*} obj 对象
  4. */
  5. export function objTypeOf(obj: any): string {
  6. const map = {
  7. '[object Boolean]': 'boolean',
  8. '[object Number]': 'number',
  9. '[object String]': 'string',
  10. '[object Function]': 'function',
  11. '[object Array]': 'array',
  12. '[object Date]': 'date',
  13. '[object RegExp]': 'regExp',
  14. '[object Undefined]': 'undefined',
  15. '[object Null]': 'null',
  16. '[object Object]': 'object',
  17. '[object Blob]': 'blob',
  18. };
  19. return map[Object.prototype.toString.call(obj)];
  20. }
  21. /**
  22. * 将目标对象中有的属性值与源对象中的属性值合并
  23. * @param {Object} target 目标对象
  24. * @param {Object} sources 源对象
  25. */
  26. export function objAssign<T extends object>(target: T, sources: object): T {
  27. const targ = { ...target };
  28. Object.keys(targ).forEach((k) => {
  29. targ[k] = Object.prototype.hasOwnProperty.call(sources, k)
  30. ? sources[k]
  31. : targ[k];
  32. });
  33. return targ;
  34. }
  35. /**
  36. * 使用目标对象中有的属性值修改源对象中的属性值
  37. * @param {Object} target 目标对象
  38. * @param {Object} sources 源对象
  39. */
  40. export function objModifyAssign(target: object, sources: object): void {
  41. Object.keys(target).forEach((k) => {
  42. if (Object.prototype.hasOwnProperty.call(sources, k)) {
  43. target[k] = sources[k];
  44. }
  45. });
  46. }
  47. /**
  48. * 获取随机code,默认获取16位
  49. * @param {Number} len 推荐8的倍数
  50. *
  51. */
  52. export function randomCode(len = 16) {
  53. if (len <= 0) return '';
  54. const steps = Math.ceil(len / 8);
  55. const stepNums = [];
  56. for (let i = 0; i < steps; i++) {
  57. const ranNum = Math.random().toString(32).slice(-8);
  58. stepNums.push(ranNum);
  59. }
  60. return stepNums.join('');
  61. }
  62. /**
  63. * 序列化参数
  64. * @param {Object} params 参数对象
  65. */
  66. export function qsParams(params: Record<string, any>) {
  67. return Object.entries(params)
  68. .map((el) => `${el[0]}=${el[1]}`)
  69. .join('&');
  70. }
  71. /**
  72. *
  73. * @param {String} format 时间格式
  74. * @param {Date} date 需要格式化的时间对象
  75. */
  76. export function formatDate(
  77. format = 'YYYY/MM/DD HH:mm:ss',
  78. date = new Date()
  79. ): string {
  80. if (objTypeOf(date) !== 'date') return '';
  81. const options = {
  82. 'Y+': date.getFullYear(),
  83. 'M+': date.getMonth() + 1,
  84. 'D+': date.getDate(),
  85. 'H+': date.getHours(),
  86. 'm+': date.getMinutes(),
  87. 's+': date.getSeconds(),
  88. };
  89. Object.entries(options).forEach(([key, val]) => {
  90. if (new RegExp(`(${key})`).test(format)) {
  91. const zeros = key === 'Y+' ? '0000' : '00';
  92. const valLen = `${val}`.length;
  93. const value = (zeros + val).substr(valLen);
  94. format = format.replace(RegExp.$1, value);
  95. }
  96. });
  97. return format;
  98. }
  99. /**
  100. * 获取时间长度文字
  101. * @param {Number} timeNumber 时间数值,单位:毫秒
  102. */
  103. export function timeNumberToText(timeNumber: number): string {
  104. const DAY_TIME = 24 * 60 * 60 * 1000;
  105. const HOUR_TIME = 60 * 60 * 1000;
  106. const MINUTE_TIME = 60 * 1000;
  107. const SECOND_TIME = 1000;
  108. let [day, hour, minute, second] = [0, 0, 0, 0];
  109. let residueTime = timeNumber;
  110. if (residueTime >= DAY_TIME) {
  111. day = Math.floor(residueTime / DAY_TIME);
  112. residueTime -= day * DAY_TIME;
  113. }
  114. if (residueTime >= HOUR_TIME) {
  115. hour = Math.floor(residueTime / HOUR_TIME);
  116. residueTime -= hour * HOUR_TIME;
  117. }
  118. if (residueTime >= MINUTE_TIME) {
  119. minute = Math.floor(residueTime / MINUTE_TIME);
  120. residueTime -= minute * MINUTE_TIME;
  121. }
  122. if (residueTime >= SECOND_TIME) {
  123. second = Math.round(residueTime / SECOND_TIME);
  124. }
  125. return [`${day}天`, `${hour}小时`, `${minute}分钟`, `${second}秒`]
  126. .filter((item) => !!item)
  127. .join('');
  128. }
  129. /**
  130. * 警告时间
  131. * @param {Number} timeNumber 时间数值,单位:毫秒
  132. * @param {Number} wainingTime 最大剩余警告时间数值,单位:毫秒
  133. */
  134. export function residueFloorTime(timeNumber: number, wainingTime = 0) {
  135. if (timeNumber < 0) {
  136. return { status: 'danger', title: '已过期' };
  137. }
  138. const DAY_TIME = 24 * 60 * 60 * 1000;
  139. const HOUR_TIME = 60 * 60 * 1000;
  140. const MINUTE_TIME = 60 * 1000;
  141. const status = timeNumber < wainingTime ? 'warning' : 'primary';
  142. let [day, hour, minute] = [0, 0, 0];
  143. let residueTime = timeNumber;
  144. if (residueTime >= DAY_TIME) {
  145. day = Math.floor(residueTime / DAY_TIME);
  146. residueTime -= day * DAY_TIME;
  147. return {
  148. status,
  149. title: `剩余${day}天`,
  150. };
  151. }
  152. if (residueTime >= HOUR_TIME) {
  153. hour = Math.floor(residueTime / HOUR_TIME);
  154. residueTime -= hour * HOUR_TIME;
  155. return {
  156. status,
  157. title: `剩余${hour}小时`,
  158. };
  159. }
  160. if (residueTime >= MINUTE_TIME) {
  161. minute = Math.floor(residueTime / MINUTE_TIME);
  162. return {
  163. status,
  164. title: `剩余${minute}分钟`,
  165. };
  166. }
  167. return {
  168. status,
  169. title: `不足1分钟`,
  170. };
  171. }
  172. export function parseTimeRangeDateAndTime(startTime: number, endTime: number) {
  173. if (!startTime || !endTime)
  174. return {
  175. date: '',
  176. time: '',
  177. };
  178. const st = formatDate('YYYY-MM-DD HH:mm', new Date(startTime)).split(' ');
  179. const et = formatDate('YYYY-MM-DD HH:mm', new Date(endTime)).split(' ');
  180. return {
  181. date: st[0],
  182. time: `${st[1]}-${et[1]}`,
  183. };
  184. }
  185. export function parseTimeRangeDateAndTimeContent(
  186. startTime: number,
  187. endTime: number
  188. ) {
  189. const { date, time } = parseTimeRangeDateAndTime(startTime, endTime);
  190. return `${date} ${time}`;
  191. }
  192. /**
  193. * 获取本地时间,格式:年月日时分秒
  194. */
  195. export function localNowDateTime() {
  196. return formatDate('YYYY年MM月DD日HH时mm分ss秒');
  197. }
  198. /**
  199. *
  200. * @param {Number} time 时间戳
  201. */
  202. export function getTimeDatestamp(time: number) {
  203. const date = formatDate('YYYY-MM-DD HH:mm', new Date(time)).split(' ')[0];
  204. return new Date(`${date} 00:00:00`).getTime();
  205. }
  206. /**
  207. * 获取指定元素个数的数组
  208. * @param {Number} num
  209. */
  210. export function getNumList(num: number) {
  211. return '#'.repeat(num).split('');
  212. }
  213. /**
  214. * 清除html标签
  215. * @param {String} str html字符串
  216. */
  217. export function removeHtmlTag(str: string) {
  218. return str.replace(/<[^>]+>/g, '');
  219. }
  220. /**
  221. * 计算总数
  222. * @param {Array} dataList 需要统计的数组
  223. */
  224. export function calcSum(dataList: number[]) {
  225. if (!dataList.length) return 0;
  226. return dataList.reduce((total, item) => {
  227. return total + item;
  228. }, 0);
  229. }
  230. /**
  231. * 计算评卷数
  232. * @param {Array} dataList 需要统计的数组
  233. */
  234. export function calcAvg(dataList: number[]) {
  235. if (!dataList.length) return 0;
  236. return calcSum(dataList) / dataList.length;
  237. }
  238. /** 获取数组最大数 */
  239. export function maxNum(dataList: number[]) {
  240. if (!dataList.length) return 0;
  241. return Math.max.apply(null, dataList);
  242. }
  243. export function isEmptyObject(obj: object) {
  244. return !Object.keys(obj).length;
  245. }
  246. export function humpToLowLine(a: string) {
  247. return a
  248. .replace(/([A-Z])/g, '-$1')
  249. .toLowerCase()
  250. .slice(1);
  251. }
  252. export function pickByNotNull(params: Record<string, any>) {
  253. const nData = {};
  254. (Object.entries(params) as [string, any][]).forEach(([key, val]) => {
  255. if (val === null || val === 'null' || val === '') return;
  256. nData[key] = val;
  257. });
  258. return nData;
  259. }
  260. export function autoSubmitForm(url: string, params: Record<string, any>) {
  261. const form = document.createElement('form');
  262. form.action = url;
  263. form.method = 'post';
  264. (Object.entries(params) as [string, any][]).forEach(([key, val]) => {
  265. const input = document.createElement('input');
  266. input.type = 'hidden';
  267. input.name = key;
  268. input.value = val;
  269. form.appendChild(input);
  270. });
  271. document.body.appendChild(form);
  272. form.submit();
  273. }
  274. export function blobToText(blob: Blob): Promise<string | ArrayBuffer | null> {
  275. return new Promise((resolve, reject) => {
  276. const reader = new FileReader();
  277. reader.readAsText(blob, 'utf-8');
  278. reader.onload = () => {
  279. resolve(reader.result);
  280. };
  281. reader.onerror = () => {
  282. reject();
  283. };
  284. });
  285. }
  286. export function parseHrefParam(
  287. urlStr: string,
  288. paramName = ''
  289. ): Record<string, any> | null {
  290. if (!urlStr) return null;
  291. const url = new URL(urlStr);
  292. const urlParams = new URLSearchParams(url.search);
  293. if (paramName) return urlParams.get(paramName as string);
  294. const params = {};
  295. (urlParams.entries() as [string, string][]).forEach(([k, v]) => {
  296. params[k] = v;
  297. });
  298. return params;
  299. }
  300. /**
  301. * 将字典数据转成为option列表数据
  302. * @param data 字典数据
  303. * @returns option列表
  304. */
  305. export function dictToOption(dict: Record<any, string>) {
  306. const options = [] as Array<{
  307. value: number | string | boolean;
  308. label: string;
  309. }>;
  310. const booleanStrs = ['true', 'false'];
  311. Object.keys(dict).forEach((k) => {
  312. options.push({
  313. value: booleanStrs.includes(k) ? (JSON.parse(k) as boolean) : k,
  314. label: dict[k],
  315. });
  316. });
  317. return options;
  318. }
  319. /**
  320. * 蛇形转驼峰
  321. * @param name 蛇形字符
  322. * @returns 驼峰字符
  323. */
  324. export function snakeToHump(name: string): string {
  325. return name
  326. .split('-')
  327. .map((item) => item[0].toLocaleUpperCase() + item.substring(1))
  328. .join('');
  329. }
  330. export function deepCopy<T>(data: T): T {
  331. return JSON.parse(JSON.stringify(data));
  332. }