utils.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. import { MenuProps, message } from "antd";
  2. import { RcFile } from "antd/lib/upload";
  3. import dayjs from 'dayjs';
  4. // 排序这是比较函数
  5. export const compare = (field: string, order: 'descend' | 'ascend') => {
  6. // descend 降序 大到小 ascend 升序 小到大
  7. if (order === 'ascend') {
  8. return function (m: any, n: any) {
  9. var a = m[field];
  10. var b = n[field];
  11. return a - b; //升序
  12. }
  13. } else {
  14. return function (m: any, n: any) {
  15. var a = m[field];
  16. var b = n[field];
  17. return b - a; //降序
  18. }
  19. }
  20. }
  21. // 返回别名
  22. export const getChannelName = (name: string) => {
  23. let newName = name
  24. let abridgeServer: string[] = ['知定', '巨网', '广联', '太古', '云广', '傲星', '弘捷', '开域']
  25. let asName = abridgeServer.find((item: string) => name?.indexOf(item) !== -1)
  26. if (asName) {
  27. newName = asName
  28. } else if (newName?.length > 5) {
  29. newName = newName?.slice(2, 5) + '...'
  30. }
  31. return newName
  32. }
  33. // 输入文案时判断
  34. export const txtLength = (value?: string) => {
  35. if (value) {
  36. let length = value?.length
  37. let text = value?.replace(/[\x00-\xff]/g, '')
  38. return text?.length * 3 + Number(((length - text?.length) / 2).toFixed()) + 3
  39. } else {
  40. return 0
  41. }
  42. }
  43. /** 获取base64 */
  44. export const getBase64 = (file: RcFile, callback: (url: string) => void) => {
  45. const reader = new FileReader();
  46. reader.addEventListener('load', () => callback(reader.result as string));
  47. reader.readAsDataURL(file);
  48. };
  49. /** 获取图片上传宽高 */
  50. export const getImgSizeProper = (file: RcFile): Promise<void> => {
  51. return new Promise((resolve: (value: any | PromiseLike<void>) => void) => {
  52. let img: any = new Image();
  53. let _URL = window.URL || window.webkitURL;
  54. img.onload = function (e: any) {
  55. resolve({ width: this.width, height: this.height })
  56. }
  57. img.src = _URL.createObjectURL(file);
  58. })
  59. }
  60. export const getImgSizeProperUrl = (url: string): Promise<void> => {
  61. return new Promise((resolve: (value: any | PromiseLike<void>) => void) => {
  62. let img: any = new Image();
  63. let _URL = window.URL || window.webkitURL;
  64. img.onload = function (e: any) {
  65. resolve({ width: this.width, height: this.height })
  66. }
  67. img.onerror = function () {
  68. resolve({ width: 100, height: 100 })
  69. }
  70. img.src = url;
  71. })
  72. }
  73. // 设置导航
  74. type MenuItem = Required<MenuProps>['items'][number];
  75. export function getItem(
  76. label: React.ReactNode,
  77. key?: React.Key | null,
  78. icon?: React.ReactNode,
  79. children?: MenuItem[],
  80. ): MenuItem {
  81. let newChildren: MenuItem[] = []
  82. if (children && children?.length > 0) {
  83. newChildren = children?.map((item: any, i: number) => {
  84. if (item.children?.length > 0) {
  85. return getItem(item?.title, item?.path, item?.icon, item.children)
  86. }
  87. return getItem(item?.title, item?.path, item?.icon)
  88. })
  89. }
  90. return { key, icon, children: newChildren?.length > 0 ? newChildren : undefined, label } as MenuItem;
  91. }
  92. // 处理路由
  93. export function getRouter(data: any): any {
  94. if (data) {
  95. let arr = Object.keys(data)?.filter(key => data[key]?.length > 0)
  96. let obj: any = {}
  97. arr.forEach(a => {
  98. obj[a] = data[a]
  99. })
  100. let menus: any = Object.values(obj).sort((a: any, b: any) => { return a[0]?.orderNum - b[0]?.orderNum })
  101. let menu: any = {}
  102. menus[0]?.forEach((item: { path: string, children: any[] }) => {
  103. let belongPlatform = item?.path?.replace('/', '')
  104. let newChildren: any[] = []
  105. if (item?.children?.length > 0) {
  106. newChildren = getRouterItem(item?.children, belongPlatform)
  107. }
  108. menu[belongPlatform] = [{ ...item, belongPlatform, children: newChildren }]
  109. });
  110. return menu
  111. } else {
  112. return {}
  113. }
  114. }
  115. // 处理子路由
  116. export function getRouterItem(children: any[], belongPlatform: string): any[] {
  117. if (children?.length > 0) {
  118. return children.map((item: { children: any[] }) => {
  119. let newChildren: any[] = []
  120. if (item?.children?.length > 0) {
  121. newChildren = getRouterItem(item?.children, belongPlatform)
  122. }
  123. return { ...item, belongPlatform, children: newChildren }
  124. })
  125. }
  126. return []
  127. }
  128. /**
  129. * 点击复制
  130. *@param str 要复制的文字
  131. *@param cb 将message 方法传进来可避免警告
  132. * */
  133. export const copy = (str: string, cb?: any) => {
  134. let element = document.createElement("textarea");
  135. element.id = 'myTextarea'
  136. element.textContent = str
  137. document.body.append(element);
  138. (document.getElementById('myTextarea') as any).select();
  139. document.execCommand("Copy")
  140. document.body.removeChild(element);
  141. cb?.success(`复制成功:${str}`, 1) ?? message.success(`复制成功:${str}`, 1)
  142. }
  143. /**
  144. * 格式化文件大小, 输出成带单位的字符串
  145. * @method formatSize
  146. * @grammar Base.formatSize( size ) => String
  147. * @grammar Base.formatSize( size, pointLength ) => String
  148. * @grammar Base.formatSize( size, pointLength, units ) => String
  149. * @param {Number} size 文件大小
  150. * @param {Number} [pointLength=2] 精确到的小数点数。
  151. * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节,到千字节,一直往上指定。如果单位数组里面只指定了到了K(千字节),同时文件大小大于M, 此方法的输出将还是显示成多少K.
  152. * @example
  153. * console.log( Base.formatSize( 100 ) ); // => 100B
  154. * console.log( Base.formatSize( 1024 ) ); // => 1.00K
  155. * console.log( Base.formatSize( 1024, 0 ) ); // => 1K
  156. * console.log( Base.formatSize( 1024 * 1024 ) ); // => 1.00M
  157. * console.log( Base.formatSize( 1024 * 1024 * 1024 ) ); // => 1.00G
  158. * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) ); // => 1024MB
  159. */
  160. export const formatSize = (size: number | undefined, pointLength?: number, units?: string[]) => {
  161. if (!size) return '0B'
  162. let unit;
  163. units = units || ['B', 'K', 'M', 'G', 'TB'];
  164. while ((unit = units.shift()) && size > 1024) {
  165. size = size / 1024;
  166. }
  167. return (unit === 'B' ? size : size.toFixed(pointLength || 2)) + (unit || 'B');
  168. }
  169. /**
  170. * 拼接oss参数获取视频首针图
  171. * @param videoUrl
  172. */
  173. export const getVideoImgUrl = (videoUrl: string) => {
  174. return videoUrl + "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto"
  175. }
  176. /**
  177. * 获取音频时长
  178. * @param file
  179. * @returns
  180. */
  181. export const getAudioTime = (file: RcFile) => {
  182. return new Promise((resolve) => {
  183. let url = URL.createObjectURL(file);//获取录音时长
  184. let audioElement = new Audio(url);//audio也可获取视频的时长
  185. let duration;
  186. function callback() {
  187. duration = audioElement.duration;
  188. resolve(duration.toFixed(1))
  189. audioElement.removeEventListener("loadedmetadata", callback)
  190. }
  191. audioElement.addEventListener("loadedmetadata", callback)
  192. })
  193. }
  194. /**
  195. * 随机生成字符串
  196. * @param flag
  197. * @param min
  198. * @param max
  199. * @returns string
  200. */
  201. export const randomString = (flag: boolean, min: number, max: number) => {
  202. let str = "", range = min
  203. let arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
  204. if (flag) {
  205. range = Math.round(Math.random() * (max - min)) + min;
  206. }
  207. for (let i = 0; i < range; i++) {
  208. let pos = Math.round(Math.random() * (arr.length - 1));
  209. str += arr[pos];
  210. }
  211. return str;
  212. }
  213. // 数组分组
  214. export const groupBy = (array: any[], f: (item: any) => any[], isObject?: boolean) => {
  215. const groups: any = {};
  216. array.forEach(function (o) { //注意这里必须是forEach 大写
  217. const group = JSON.stringify(f(o));
  218. groups[group] = groups[group] || [];
  219. groups[group].push(o);
  220. });
  221. if (isObject) {
  222. return groups
  223. }
  224. return Object.keys(groups).map(function (group) {
  225. return groups[group];
  226. });
  227. }
  228. /**
  229. * 日期处理
  230. * @param timestamp 时间戳1703635630000
  231. * @returns
  232. */
  233. export const formatTimeDifference = (timestamp: string): string => {
  234. const currentTime = dayjs();
  235. const targetTime = dayjs(timestamp);
  236. const minuteDifference = currentTime.diff(targetTime, 'minute');
  237. if (minuteDifference < 3) {
  238. return '刚刚';
  239. } else if (minuteDifference <= 5) {
  240. return '5分钟前';
  241. } else if (minuteDifference <= 10) {
  242. return '10分钟前';
  243. } else if (minuteDifference <= 30) {
  244. return '30分钟前';
  245. } else if (minuteDifference <= 24 * 60 && currentTime.isSame(targetTime, 'day')) {
  246. return `今天 ${targetTime.format('HH:mm')}`;
  247. } else if (minuteDifference <= 48 * 60 && currentTime.subtract(1, 'day').isSame(targetTime, 'day')) {
  248. return `昨天 ${targetTime.format('HH:mm')}`;
  249. } else {
  250. if (targetTime.isSame(currentTime, 'week')) {
  251. return '周' + { 1: '一', 2: '二', 3: '三', 4: '四', 5: '五', 6: '六', 7: '天' }[targetTime.day()] + " " + targetTime.format('HH:mm');
  252. } else {
  253. return targetTime.format('YYYY-MM-DD HH:mm:ss');
  254. }
  255. }
  256. };
  257. /**
  258. * 判断2个时间戳是否相差2分钟之内
  259. * @param timestamp
  260. * @param lastTimestamp
  261. * @returns
  262. */
  263. export const isTimeDiffTwo = (timestamp: number, lastTimestamp: number): boolean => {
  264. const currentTime = dayjs(timestamp);
  265. const targetTime = dayjs(lastTimestamp);
  266. const minuteDifference = currentTime.diff(targetTime, 'minute');
  267. if (minuteDifference < 2)
  268. return true
  269. else return false
  270. }
  271. /**
  272. * 给定最小宽度最大宽度 按比例处理图片 [width, height] = adjustSize(widthO, heightO, 100, 400);
  273. * @param width
  274. * @param height
  275. * @param minSize 最小尺寸
  276. * @param maxSize 最大尺寸
  277. * @returns
  278. */
  279. export const adjustSize = (width: number, height: number, minSize: number, maxSize: number): [number, number] => {
  280. if (width === height) {
  281. if (width <= minSize) {
  282. return [minSize, minSize];
  283. } else if (width > maxSize) {
  284. return [maxSize, maxSize];
  285. }
  286. } else {
  287. if (width <= minSize) {
  288. return [minSize, minSize / width * height];
  289. } else if (width > maxSize) {
  290. let newW = maxSize
  291. let newH = maxSize / width * height
  292. if (newH > (maxSize * 1.4) && newW > minSize) {
  293. newH = minSize / newW * newH
  294. newW = minSize
  295. }
  296. return [newW, newH];
  297. }
  298. }
  299. return [width, height];
  300. };
  301. /**
  302. * 下载文件
  303. * @param url 文件地址
  304. * @param back 返回下载进度
  305. */
  306. export const downloadFile = (url: string, name: string, back?: (vale: number) => void) => {
  307. const fileName = name; // 可以自定义下载的文件名
  308. let link = url;
  309. let x = new XMLHttpRequest();
  310. x.open('GET', link, true);
  311. x.responseType = 'blob';
  312. // 监听下载进度
  313. x.onprogress = (e) => {
  314. if (e.lengthComputable) {
  315. const percentComplete = (e.loaded / e.total) * 100;
  316. // 这里可以根据需要更新 UI,显示下载进度
  317. back?.(Number(percentComplete.toFixed(1)))
  318. }
  319. };
  320. x.onload = (e) => {
  321. let url = window.URL.createObjectURL(x.response);
  322. let a = document.createElement('a');
  323. a.href = url;
  324. a.download = fileName;
  325. a.click();
  326. };
  327. x.send();
  328. }
  329. /**
  330. * 找2个数组不同元素
  331. * @param arr1
  332. * @param arr2
  333. * @returns
  334. */
  335. export const getArrDifference = (arr1: any[], arr2: any[]) => {
  336. return arr1.concat(arr2).filter((v, i, arr) => {
  337. return arr.indexOf(v) === arr.lastIndexOf(v);
  338. });
  339. }
  340. /**
  341. * file转buffer
  342. * @param file
  343. * @returns
  344. */
  345. export const readFileAsBuffer = (file) => {
  346. return new Promise((resolve) => {
  347. const reader = new FileReader();
  348. reader.onload = (e) => resolve(e.target.result);
  349. reader.readAsArrayBuffer(file);
  350. });
  351. };
  352. /**
  353. * 字符串截取
  354. * @param str
  355. * @param bytes
  356. * @returns
  357. */
  358. export const cutByBytes = (str: string, bytes: number) => {
  359. let result = '';
  360. let byteCount = 0;
  361. for (let char of str) {
  362. const charSize = char.charCodeAt(0) > 255 ? 3 : 1;
  363. if (byteCount + charSize > bytes) break;
  364. result += char;
  365. byteCount += charSize;
  366. }
  367. return result !== str ? result + '...' : str;
  368. }
  369. /**
  370. * 对象去空
  371. * @param obj
  372. * @returns
  373. */
  374. export const removeEmptyValues = (obj: { [x: string]: any }) => {
  375. for (const key in obj) {
  376. if (obj[key] === null || obj[key] === undefined || obj[key] === '') {
  377. delete obj[key];
  378. }
  379. }
  380. return obj;
  381. }