diff --git a/.env.production b/.env.production index 994ff9eec..d573192d6 100644 --- a/.env.production +++ b/.env.production @@ -7,7 +7,7 @@ VITE_PUBLIC_PATH = / # Delete console VITE_DROP_CONSOLE = true -# Whether to enable gizp or brotli compression +# Whether to enable gzip or brotli compression # Optional: gzip | brotli | none # If you need multiple forms, you can use `,` to separate VITE_BUILD_COMPRESS = 'none' diff --git a/src/App.vue b/src/App.vue index e629105e0..79e548442 100644 --- a/src/App.vue +++ b/src/App.vue @@ -22,10 +22,12 @@ setup() { // support Multi-language const { antConfigLocale, setLocale } = useLocale(); + setLocale(); // Initialize vuex internal system configuration initAppConfigStore(); + // Create a lock screen monitor const lockEvent = useLockPage(); diff --git a/src/components/Form/src/hooks/useFormEvents.ts b/src/components/Form/src/hooks/useFormEvents.ts index 8b37ca7aa..d8602923e 100644 --- a/src/components/Form/src/hooks/useFormEvents.ts +++ b/src/components/Form/src/hooks/useFormEvents.ts @@ -5,10 +5,10 @@ import type { NamePath } from 'ant-design-vue/lib/form/interface'; import { unref, toRaw } from 'vue'; import { isArray, isFunction, isObject, isString } from '/@/utils/is'; -import { deepMerge, unique } from '/@/utils'; +import { deepMerge } from '/@/utils'; import { dateItemType, handleInputNumberValue } from '../helper'; import { dateUtil } from '/@/utils/dateUtil'; -import { cloneDeep } from 'lodash-es'; +import { cloneDeep, uniqBy } from 'lodash-es'; import { error } from '/@/utils/log'; interface UseFormActionContext { @@ -160,7 +160,7 @@ export function useFormEvents({ } }); }); - schemaRef.value = unique(schema, 'field'); + schemaRef.value = uniqBy(schema, 'field'); } function getFieldsValue(): Recordable { diff --git a/src/components/Menu/src/useOpenKeys.ts b/src/components/Menu/src/useOpenKeys.ts index e2078ff61..14ea42f94 100644 --- a/src/components/Menu/src/useOpenKeys.ts +++ b/src/components/Menu/src/useOpenKeys.ts @@ -5,7 +5,7 @@ import type { MenuState } from './types'; import { computed, Ref, toRaw } from 'vue'; import { unref } from 'vue'; -import { es6Unique } from '/@/utils'; +import { uniq } from 'lodash-es'; import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; import { getAllParentPath } from '/@/router/helper/menuHelper'; import { useTimeoutFn } from '/@/hooks/core/useTimeout'; @@ -31,10 +31,7 @@ export function useOpenKeys( return; } if (!unref(accordion)) { - menuState.openKeys = es6Unique([ - ...menuState.openKeys, - ...getAllParentPath(menuList, path), - ]); + menuState.openKeys = uniq([...menuState.openKeys, ...getAllParentPath(menuList, path)]); } else { menuState.openKeys = getAllParentPath(menuList, path); } diff --git a/src/components/SimpleMenu/src/useOpenKeys.ts b/src/components/SimpleMenu/src/useOpenKeys.ts index d32bc78fc..38cba8da0 100644 --- a/src/components/SimpleMenu/src/useOpenKeys.ts +++ b/src/components/SimpleMenu/src/useOpenKeys.ts @@ -4,8 +4,9 @@ import type { MenuState } from './types'; import { computed, Ref, toRaw } from 'vue'; import { unref } from 'vue'; -import { es6Unique } from '/@/utils'; +import { uniq } from 'lodash-es'; import { getAllParentPath } from '/@/router/helper/menuHelper'; + import { useTimeoutFn } from '/@/hooks/core/useTimeout'; export function useOpenKeys( @@ -31,7 +32,7 @@ export function useOpenKeys( } const keys = getAllParentPath(menuList, path); if (!unref(accordion)) { - menuState.openNames = es6Unique([...menuState.openNames, ...keys]); + menuState.openNames = uniq([...menuState.openNames, ...keys]); } else { menuState.openNames = keys; } diff --git a/src/components/VirtualScroll/src/index.tsx b/src/components/VirtualScroll/src/index.tsx index 1e17ee648..2f827237f 100644 --- a/src/components/VirtualScroll/src/index.tsx +++ b/src/components/VirtualScroll/src/index.tsx @@ -11,12 +11,22 @@ import { } from 'vue'; import { useEventListener } from '/@/hooks/event/useEventListener'; -import { convertToUnit } from '/@/components/util'; import { props as basicProps } from './props'; import { getSlot } from '/@/utils/helper/tsxHelper'; import './index.less'; const prefixCls = 'virtual-scroll'; + +function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined { + if (str == null || str === '') { + return undefined; + } else if (isNaN(+str!)) { + return String(str); + } else { + return `${Number(str)}${unit}`; + } +} + export default defineComponent({ name: 'VirtualScroll', props: basicProps, diff --git a/src/components/registerGlobComp.ts b/src/components/registerGlobComp.ts index 00f956036..0e758ec95 100644 --- a/src/components/registerGlobComp.ts +++ b/src/components/registerGlobComp.ts @@ -3,42 +3,6 @@ import { Button } from './Button'; import { // Need Button as AntButton, - - // Optional - // Select, - // Alert, - // Checkbox, - // DatePicker, - // Radio, - // Switch, - // Card, - // List, - // Tabs, - // Descriptions, - // Tree, - // Table, - // Divider, - // Modal, - // Drawer, - // Dropdown, - // Tag, - // Tooltip, - // Badge, - // Popover, - // Upload, - // Transfer, - // Steps, - // PageHeader, - // Result, - // Empty, - // Avatar, - // Menu, - // Breadcrumb, - // Form, - // Input, - // Row, - // Col, - // Spin, } from 'ant-design-vue'; import { App } from 'vue'; @@ -47,45 +11,6 @@ const compList = [Icon, Button, AntButton.Group]; export function registerGlobComp(app: App) { compList.forEach((comp: any) => { - app.component(comp.name, comp); + app.component(comp.name || comp.displayName, comp); }); - - // Optional - // If you need to customize global components, you can write here - // If you don’t need it, you can delete it - // app - // .use(Select) - // .use(Alert) - // .use(Breadcrumb) - // .use(Checkbox) - // .use(DatePicker) - // .use(Radio) - // .use(Switch) - // .use(Card) - // .use(List) - // .use(Descriptions) - // .use(Tree) - // .use(Table) - // .use(Divider) - // .use(Modal) - // .use(Drawer) - // .use(Dropdown) - // .use(Tag) - // .use(Tooltip) - // .use(Badge) - // .use(Popover) - // .use(Upload) - // .use(Transfer) - // .use(Steps) - // .use(PageHeader) - // .use(Result) - // .use(Empty) - // .use(Avatar) - // .use(Menu) - // .use(Tabs) - // .use(Form) - // .use(Input) - // .use(Row) - // .use(Col) - // .use(Spin); } diff --git a/src/components/types.ts b/src/components/types.ts deleted file mode 100644 index b4702bda1..000000000 --- a/src/components/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineComponent } from 'vue'; - -export type Component = - | ReturnType - | (() => Promise) - | (() => Promise); diff --git a/src/components/util.tsx b/src/components/util.tsx deleted file mode 100644 index a46ff1e68..000000000 --- a/src/components/util.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import type { VNodeChild } from 'vue'; - -export function convertToUnit( - str: string | number | null | undefined, - unit = 'px' -): string | undefined { - if (str == null || str === '') { - return undefined; - } else if (isNaN(+str!)) { - return String(str); - } else { - return `${Number(str)}${unit}`; - } -} - -/** - * Camelize a hyphen-delimited string. - */ -const camelizeRE = /-(\w)/g; -export const camelize = (str: string): string => { - return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : '')); -}; - -export function wrapInArray(v: T | T[] | null | undefined): T[] { - return v != null ? (Array.isArray(v) ? v : [v]) : []; -} - -const pattern = { - styleList: /;(?![^(]*\))/g, - styleProp: /:(.*)/, -} as const; - -function parseStyle(style: string) { - const styleMap: Recordable = {}; - - for (const s of style.split(pattern.styleList)) { - let [key, val] = s.split(pattern.styleProp); - key = key.trim(); - if (!key) { - continue; - } - // May be undefined if the `key: value` pair is incomplete. - if (typeof val === 'string') { - val = val.trim(); - } - styleMap[camelize(key)] = val; - } - - return styleMap; -} - -/** - * Intelligently merges data for createElement. - * Merges arguments left to right, preferring the right argument. - * Returns new VNodeData object. - */ -export function mergeData(...vNodeData: VNodeChild[]): VNodeChild; -export function mergeData(...args: any[]): VNodeChild { - const mergeTarget: any = {}; - let i: number = args.length; - let prop: string; - - // Allow for variadic argument length. - while (i--) { - // Iterate through the data properties and execute merge strategies - // Object.keys eliminates need for hasOwnProperty call - for (prop of Object.keys(args[i])) { - switch (prop) { - // Array merge strategy (array concatenation) - case 'class': - case 'directives': - if (args[i][prop]) { - mergeTarget[prop] = mergeClasses(mergeTarget[prop], args[i][prop]); - } - break; - case 'style': - if (args[i][prop]) { - mergeTarget[prop] = mergeStyles(mergeTarget[prop], args[i][prop]); - } - break; - // Space delimited string concatenation strategy - case 'staticClass': - if (!args[i][prop]) { - break; - } - if (mergeTarget[prop] === undefined) { - mergeTarget[prop] = ''; - } - if (mergeTarget[prop]) { - // Not an empty string, so concatenate - mergeTarget[prop] += ' '; - } - mergeTarget[prop] += args[i][prop].trim(); - break; - // Object, the properties of which to merge via array merge strategy (array concatenation). - // Callback merge strategy merges callbacks to the beginning of the array, - // so that the last defined callback will be invoked first. - // This is done since to mimic how Object.assign merging - // uses the last given value to assign. - case 'on': - case 'nativeOn': - if (args[i][prop]) { - mergeTarget[prop] = mergeListeners(mergeTarget[prop], args[i][prop]); - } - break; - // Object merge strategy - case 'attrs': - case 'props': - case 'domProps': - case 'scopedSlots': - case 'staticStyle': - case 'hook': - case 'transition': - if (!args[i][prop]) { - break; - } - if (!mergeTarget[prop]) { - mergeTarget[prop] = {}; - } - mergeTarget[prop] = { ...args[i][prop], ...mergeTarget[prop] }; - break; - // Reassignment strategy (no merge) - default: - // slot, key, ref, tag, show, keepAlive - if (!mergeTarget[prop]) { - mergeTarget[prop] = args[i][prop]; - } - } - } - } - - return mergeTarget; -} - -export function mergeStyles( - target: undefined | string | object[] | object, - source: undefined | string | object[] | object -) { - if (!target) return source; - if (!source) return target; - - target = wrapInArray(typeof target === 'string' ? parseStyle(target) : target); - - return (target as object[]).concat(typeof source === 'string' ? parseStyle(source) : source); -} - -export function mergeClasses(target: any, source: any) { - if (!source) return target; - if (!target) return source; - - return target ? wrapInArray(target).concat(source) : source; -} - -export function mergeListeners( - target: Indexable | undefined, - source: Indexable | undefined -) { - if (!target) return source; - if (!source) return target; - - let event: string; - - for (event of Object.keys(source)) { - // Concat function to array of functions if callback present. - if (target[event]) { - // Insert current iteration data in beginning of merged array. - target[event] = wrapInArray(target[event]); - (target[event] as Function[]).push(...wrapInArray(source[event])); - } else { - // Straight assign. - target[event] = source[event]; - } - } - - return target; -} diff --git a/src/hooks/core/useDebouncedRef.ts b/src/hooks/core/useDebouncedRef.ts deleted file mode 100644 index 2345e36dc..000000000 --- a/src/hooks/core/useDebouncedRef.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { customRef } from 'vue'; - -export function useDebouncedRef(value: T, delay = 100) { - let timeout: TimeoutHandle; - return customRef((track, trigger) => { - return { - get() { - track(); - return value; - }, - set(newValue: T) { - clearTimeout(timeout); - timeout = setTimeout(() => { - value = newValue; - trigger(); - }, delay); - }, - }; - }); -} diff --git a/src/hooks/core/useEffect.ts b/src/hooks/core/useEffect.ts deleted file mode 100644 index 176c78a0d..000000000 --- a/src/hooks/core/useEffect.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { watch } from 'vue'; -import { isFunction } from '/@/utils/is'; - -export function useEffect( - effectHandler: (deps: T[], prevDeps?: T[]) => () => void, - dependencies: T[] -) { - return watch( - dependencies, - (changedDependencies, prevDependencies, onCleanUp) => { - const effectCleaner = effectHandler(changedDependencies, prevDependencies); - if (isFunction(effectCleaner)) { - onCleanUp(effectCleaner); - } - }, - { immediate: true, deep: true } - ); -} diff --git a/src/hooks/core/useState.ts b/src/hooks/core/useState.ts deleted file mode 100644 index 7c4f3f833..000000000 --- a/src/hooks/core/useState.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { isObject } from '@vue/shared'; -import { reactive, Ref, ref, readonly } from 'vue'; -import { isFunction } from '/@/utils/is'; - -type State = ((s: T) => T) | T; -type Dispatch = (t: T) => void; - -type DispatchState = Dispatch>; - -type ResultState = Readonly>; - -export function useState( - initialState: (() => T) | T -): [ResultState, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [ResultState, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [ResultState, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [ResultState, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [ResultState, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [Readonly, DispatchState]; - -export function useState( - initialState: (() => T) | T -): [Readonly, DispatchState]; - -export function useState(initialState: (() => T) | T): [ResultState | T, DispatchState] { - if (isFunction(initialState)) { - initialState = (initialState as Fn)(); - } - - if (isObject(initialState)) { - const state = reactive({ data: initialState }) as any; - const setState = (newState: T) => { - state.data = newState; - }; - return [readonly(state), setState]; - } else { - const state = ref(initialState) as any; - const setState = (newState: T) => { - state.value = newState; - }; - return [readonly(state), setState]; - } -} diff --git a/src/layouts/iframe/index.vue b/src/layouts/iframe/index.vue index 2dae17898..d9ee7e5b8 100644 --- a/src/layouts/iframe/index.vue +++ b/src/layouts/iframe/index.vue @@ -21,9 +21,7 @@ setup() { const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive(); - const showFrame = computed(() => { - return unref(getFramePages).length > 0; - }); + const showFrame = computed(() => unref(getFramePages).length > 0); return { getFramePages, hasRenderFrame, showIframe, showFrame }; }, diff --git a/src/layouts/iframe/useFrameKeepAlive.ts b/src/layouts/iframe/useFrameKeepAlive.ts index fb06a613f..97233c8a1 100644 --- a/src/layouts/iframe/useFrameKeepAlive.ts +++ b/src/layouts/iframe/useFrameKeepAlive.ts @@ -4,7 +4,7 @@ import { computed, toRaw, unref } from 'vue'; import { tabStore } from '/@/store/modules/tab'; -import { unique } from '/@/utils'; +import { uniqBy } from 'lodash-es'; import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; @@ -40,7 +40,7 @@ export function useFrameKeepAlive() { res.push(...getAllFramePages(children)); } } - res = unique(res, 'name'); + res = uniqBy(res, 'name'); return res; } diff --git a/src/router/guard/permissionGuard.ts b/src/router/guard/permissionGuard.ts index 3fd033c01..ac20041b5 100644 --- a/src/router/guard/permissionGuard.ts +++ b/src/router/guard/permissionGuard.ts @@ -3,7 +3,7 @@ import type { Router, RouteRecordRaw } from 'vue-router'; import { permissionStore } from '/@/store/modules/permission'; import { PageEnum } from '/@/enums/pageEnum'; -import { getToken } from '/@/utils/auth'; +import { userStore } from '/@/store/modules/user'; import { PAGE_NOT_FOUND_ROUTE } from '/@/router/constant'; @@ -25,7 +25,7 @@ export function createPermissionGuard(router: Router) { return; } - const token = getToken(); + const token = userStore.getTokenState; // token does not exist if (!token) { diff --git a/src/router/types.ts b/src/router/types.ts index f893a11e6..c057d690b 100644 --- a/src/router/types.ts +++ b/src/router/types.ts @@ -1,7 +1,12 @@ import type { RouteRecordRaw } from 'vue-router'; import { RoleEnum } from '/@/enums/roleEnum'; -import type { Component } from '/@/components/types'; +import { defineComponent } from 'vue'; + +export type Component = + | ReturnType + | (() => Promise) + | (() => Promise); export interface RouteMeta { // title diff --git a/src/types/shims-volar.d.ts b/src/types/shims-volar.d.ts deleted file mode 100644 index aec6b6e5f..000000000 --- a/src/types/shims-volar.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { RouterLink, RouterView } from 'vue-router'; - -import { Button } from '/@/components/Button'; -import { Col, Row } from 'ant-design-vue'; - -declare global { - interface __VLS_GlobalComponents { - RouterLink: typeof RouterLink; - RouterView: typeof RouterView; - 'a-button': typeof Button; - 'a-col': typeof Col; - 'a-row': typeof Row; - } -} diff --git a/src/utils/auth/index.ts b/src/utils/auth/index.ts deleted file mode 100644 index bbdebe4e4..000000000 --- a/src/utils/auth/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { userStore } from '/@/store/modules/user'; - -/** - * @description: Get token - * @return jwt token - */ -export function getToken(): string { - return userStore.getTokenState; -} diff --git a/src/utils/cache/cookie.ts b/src/utils/cache/cookie.ts deleted file mode 100644 index 26a854dd1..000000000 --- a/src/utils/cache/cookie.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { DEFAULT_CACHE_TIME } from '../../settings/encryptionSetting'; -import { getStorageShortName } from '/@/utils/helper/envHelper'; -import { cacheCipher } from '/@/settings/encryptionSetting'; -import Encryption from '/@/utils/encryption/aesEncryption'; - -export default class WebCookie { - private encryption: Encryption; - private hasEncrypt: boolean; - - constructor(hasEncrypt = true, key = cacheCipher.key, iv = cacheCipher.iv) { - const encryption = new Encryption({ key, iv }); - this.encryption = encryption; - this.hasEncrypt = hasEncrypt; - } - - private getKey(key: string) { - return `${getStorageShortName()}${key}`.toUpperCase(); - } - - /** - * Add cookie - * @param name cookie key - * @param value cookie value - * @param expire - * If the expiration time is not set, the default management browser will automatically delete - * e.g: - * cookieData.set('name','value',) - */ - setCookie(key: string, value: any, expire: number | null = DEFAULT_CACHE_TIME) { - value = this.hasEncrypt ? this.encryption.encryptByAES(JSON.stringify(value)) : value; - document.cookie = this.getKey(key) + '=' + value + '; Max-Age=' + expire; - } - - /** - * Get the cook value according to the key - * @param key cookie key - */ - getCookie(key: string) { - const arr = document.cookie.split('; '); - for (let i = 0; i < arr.length; i++) { - const arr2 = arr[i].split('='); - if (arr2[0] === this.getKey(key)) { - let message: any = null; - const str = arr2[1]; - if (this.hasEncrypt && str) { - message = this.encryption.decryptByAES(str); - try { - return JSON.parse(message); - } catch (e) { - return str; - } - } - return str; - } - } - return ''; - } - - /** - * Delete cookie based on cookie key - * @param key cookie key - */ - removeCookie(key: string) { - this.setCookie(key, 1, -1); - } - - /** - * clear cookie - */ - clearCookie(): void { - const keys = document.cookie.match(/[^ =;]+(?==)/g); - if (keys) { - for (let i = keys.length; i--; ) { - document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString(); - } - } - } -} diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts index e1f3f2d21..2e98d7584 100644 --- a/src/utils/domUtils.ts +++ b/src/utils/domUtils.ts @@ -73,13 +73,13 @@ export function removeClass(el: Element, cls: string) { } } /** - * 获取当前元素的left、top偏移 - * left:元素最左侧距离文档左侧的距离 - * top:元素最顶端距离文档顶端的距离 - * right:元素最右侧距离文档右侧的距离 - * bottom:元素最底端距离文档底端的距离 - * rightIncludeBody:元素最左侧距离文档右侧的距离 - * bottomIncludeBody:元素最底端距离文档最底部的距离 + * Get the left and top offset of the current element + * left: the distance between the leftmost element and the left side of the document + * top: the distance from the top of the element to the top of the document + * right: the distance from the far right of the element to the right of the document + * bottom: the distance from the bottom of the element to the bottom of the document + * rightIncludeBody: the distance between the leftmost element and the right side of the document + * bottomIncludeBody: the distance from the bottom of the element to the bottom of the document * * @description: */ diff --git a/src/utils/encryption/aesEncryption.ts b/src/utils/encryption/aesEncryption.ts index 425d20774..6b2bf8aa8 100644 --- a/src/utils/encryption/aesEncryption.ts +++ b/src/utils/encryption/aesEncryption.ts @@ -14,7 +14,7 @@ export class Encryption { this.iv = CryptoES.enc.Utf8.parse(iv); } - get getOpt(): CryptoES.lib.CipherCfg { + get getOptions(): CryptoES.lib.CipherCfg { return { mode: CryptoES.mode.CBC as any, padding: CryptoES.pad.Pkcs7, @@ -23,13 +23,11 @@ export class Encryption { } encryptByAES(str: string) { - const encrypted = CryptoES.AES.encrypt(str, this.key, this.getOpt); - return encrypted.toString(); + return CryptoES.AES.encrypt(str, this.key, this.getOptions).toString(); } decryptByAES(str: string) { - const decrypted = CryptoES.AES.decrypt(str, this.key, this.getOpt); - return decrypted.toString(CryptoES.enc.Utf8); + return CryptoES.AES.decrypt(str, this.key, this.getOptions).toString(CryptoES.enc.Utf8); } } export default Encryption; diff --git a/src/utils/http/axios/index.ts b/src/utils/http/axios/index.ts index f1c0f4845..af94a26c4 100644 --- a/src/utils/http/axios/index.ts +++ b/src/utils/http/axios/index.ts @@ -4,7 +4,6 @@ import type { AxiosResponse } from 'axios'; import type { CreateAxiosOptions, RequestOptions, Result } from './types'; import { VAxios } from './Axios'; -import { getToken } from '/@/utils/auth'; import { AxiosTransform } from './axiosTransform'; import { checkStatus } from './checkStatus'; @@ -20,6 +19,7 @@ import { errorStore } from '/@/store/modules/error'; import { errorResult } from './const'; import { useI18n } from '/@/hooks/web/useI18n'; import { createNow, formatRequestDate } from './helper'; +import { userStore } from '/@/store/modules/user'; const globSetting = useGlobSetting(); const prefix = globSetting.urlPrefix; @@ -137,7 +137,7 @@ const transform: AxiosTransform = { */ requestInterceptors: (config) => { // 请求之前处理config - const token = getToken(); + const token = userStore.getTokenState; if (token) { // jwt token config.headers.Authorization = token; diff --git a/src/utils/index.ts b/src/utils/index.ts index 1e134f106..af210fa01 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -38,24 +38,6 @@ export function deepMerge(src: any = {}, target: any = {}): T { return src; } -/** - * @description: Deduplication according to the value of an object in the array - */ -export function unique(arr: T[], key: string): T[] { - const map = new Map(); - return arr.filter((item) => { - const _item = item as any; - return !map.has(_item[key]) && map.set(_item[key], 1); - }); -} - -/** - * @description: es6 array to repeat - */ -export function es6Unique(arr: T[]): T[] { - return Array.from(new Set(arr)); -} - export function openWindow( url: string, opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean } @@ -80,20 +62,6 @@ export function getDynamicProps(props: T): Partial { return ret as Partial; } -export function getLastItem(list: T) { - if (Array.isArray(list)) { - return list.slice(-1)[0]; - } - - if (list instanceof Set) { - return Array.from(list).slice(-1)[0]; - } - - if (list instanceof Map) { - return Array.from(list.values()).slice(-1)[0]; - } -} - /** * set page Title * @param {*} title :page Title