diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..8b757b29 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a8fdeee7..8d619d2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # CHANGE LOG +## 4.0.0 + +### Feats + +- 重构 types 包设计,现在的类型包更加清晰 +- 重构 utils 包设计,该包下的所有 hook 提供了更加友好的类型提示 +- RayIframe 组件新增 lazy 属性 +- 新增 v-disabled 指令 +- demo 页面展示优化 + +### Fixes + +- 修复一些已知的 bug + +### 补充 + +> 这次花了一点时间,将模板进行重新梳理,进行了一些很大的破坏性更新改动。核心重点是 types 包与 utils 包的重大更新。不过只是做了初步的一些大方向的更新,后续的细节更新还在继续。。。 + ## 3.3.7 ### Feats diff --git a/src/App.tsx b/src/App.tsx index 78a32949..174b7db4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,6 +8,8 @@ import { get } from 'lodash-es' import { useSetting } from '@/store' import { addClass, removeClass, addStyle, colorToRgba } from '@/utils/element' +import type { SettingState } from '@/store/modules/setting/type' + const App = defineComponent({ name: 'App', setup() { @@ -22,12 +24,15 @@ const App = defineComponent({ } = __APP_CFG__ // 默认主题色 const body = document.body - const primaryColorOverride = getCache('piniaSettingStore', 'localStorage') + const primaryColorOverride = getCache( + 'piniaSettingStore', + 'localStorage', + ) const _p = get( primaryColorOverride, 'primaryColorOverride.common.primaryColor', ) - const _fp = colorToRgba(_p, 0.3) + const _fp = colorToRgba(_p || primaryColor, 0.3) /** 设置全局主题色 css 变量 */ body.style.setProperty('--ray-theme-primary-color', _p || primaryColor) diff --git a/src/appConfig/appConfig.ts b/src/appConfig/appConfig.ts index 078ba861..c75814f8 100644 --- a/src/appConfig/appConfig.ts +++ b/src/appConfig/appConfig.ts @@ -15,8 +15,11 @@ import type { LayoutSideBarLogo, PreloadingConfig, RootRoute, -} from '@/types/cfg' -import type { MenuCollapsedConfig, AppKeepAlive } from '@/types/appConfig' +} from '@/types/modules/cfg' +import type { + MenuCollapsedConfig, + AppKeepAlive, +} from '@/types/modules/appConfig' /** * diff --git a/src/appConfig/designConfig.ts b/src/appConfig/designConfig.ts index 0e6cb4ec..5d5ca5b3 100644 --- a/src/appConfig/designConfig.ts +++ b/src/appConfig/designConfig.ts @@ -11,7 +11,7 @@ /** 系统颜色风格配置入口 */ -import type { AppPrimaryColor } from '@/types/cfg' +import type { AppPrimaryColor } from '@/types/modules/cfg' import type { GlobalThemeOverrides } from 'naive-ui' /** diff --git a/src/axios/api/test.ts b/src/axios/api/test.ts index 6f5c64d9..125ce98e 100644 --- a/src/axios/api/test.ts +++ b/src/axios/api/test.ts @@ -24,6 +24,8 @@ import useRequest from '@/axios/instance' +import type { AxiosResponseBody } from '@/types/modules/axios' + interface AxiosTestResponse extends UnknownObjectKey { data: UnknownObjectKey[] city?: string diff --git a/src/axios/helper/interceptor.ts b/src/axios/helper/interceptor.ts index 82539da5..2badc7d0 100644 --- a/src/axios/helper/interceptor.ts +++ b/src/axios/helper/interceptor.ts @@ -30,6 +30,7 @@ import type { ErrorImplementQueue, FetchType, } from '@/axios/type' +import type { AnyFunc } from '@/types/modules/utils' /** 当前请求的实例 */ const axiosFetchInstance = { diff --git a/src/axios/inject/requestInject.ts b/src/axios/inject/requestInject.ts index f789c224..b2231b6a 100644 --- a/src/axios/inject/requestInject.ts +++ b/src/axios/inject/requestInject.ts @@ -39,7 +39,7 @@ const { setImplement } = useAxiosInterceptor() * 当然你也可以根据 request instance 来特殊处理, 这里暂时不做演示 */ const requestHeaderToken = (ins: RequestInterceptorConfig, mode: string) => { - const token = getCache(APP_CATCH_KEY.token) + const token = getCache(APP_CATCH_KEY.token) if (ins.url) { // TODO: 根据 url 不同是否设置 token diff --git a/src/axios/type.ts b/src/axios/type.ts index 40db396a..d954a08e 100644 --- a/src/axios/type.ts +++ b/src/axios/type.ts @@ -8,6 +8,7 @@ import type { InternalAxiosRequestConfig, AxiosResponse, } from 'axios' +import type { AnyFunc } from '@/types/modules/utils' export type AxiosHeaderValue = | AxiosHeaders diff --git a/src/components/AppComponents/AppAvatar/index.tsx b/src/components/AppComponents/AppAvatar/index.tsx index 41185515..dd5c5625 100644 --- a/src/components/AppComponents/AppAvatar/index.tsx +++ b/src/components/AppComponents/AppAvatar/index.tsx @@ -27,6 +27,7 @@ import { getCache } from '@/utils/cache' import type { PropType } from 'vue' import type { AvatarProps, SpaceProps } from 'naive-ui' +import type { SigninCallback } from '@/store/modules/signin/type' const AppAvatar = defineComponent({ name: 'AppAvatar', @@ -47,7 +48,7 @@ const AppAvatar = defineComponent({ }, }, setup(props) { - const signin = getCache(APP_CATCH_KEY.signin) + const signin = getCache(APP_CATCH_KEY.signin) const cssVars = computed(() => { const vars = { '--app-avatar-cursor': props.cursor, @@ -73,12 +74,12 @@ const AppAvatar = defineComponent({ -
{this.signin.name}
+
{this.signin?.name}
) }, diff --git a/src/components/RayChart/index.tsx b/src/components/RayChart/index.tsx index 1a11fe5d..6dcd2a55 100644 --- a/src/components/RayChart/index.tsx +++ b/src/components/RayChart/index.tsx @@ -43,6 +43,8 @@ import { cloneDeep, debounce } from 'lodash-es' import { on, off, addStyle, completeSize } from '@/utils/element' import type { PropType } from 'vue' +import type { EChartsInstance } from '@/types/modules/component' +import type { AnyFunc } from '@/types/modules/utils' export type AutoResize = | boolean diff --git a/src/components/RayIframe/src/index.tsx b/src/components/RayIframe/src/index.tsx index 1377cc73..9171ccfa 100644 --- a/src/components/RayIframe/src/index.tsx +++ b/src/components/RayIframe/src/index.tsx @@ -93,6 +93,11 @@ const RayIframe = defineComponent({ type: Object as PropType, default: () => ({}), }, + lazy: { + /** 是否延迟加载 iframe */ + type: Boolean, + default: true, + }, }, setup(props, { expose }) { const cssVars = computed(() => { @@ -160,6 +165,9 @@ const RayIframe = defineComponent({ allow={this.allow} name={this.name} title={this.title} + {...{ + loading: this.lazy ? 'lazy' : null, + }} > ), }} diff --git a/src/components/RayTable/src/components/TableSize/index.tsx b/src/components/RayTable/src/components/TableSize/index.tsx index 4d23e8ea..bdd04779 100644 --- a/src/components/RayTable/src/components/TableSize/index.tsx +++ b/src/components/RayTable/src/components/TableSize/index.tsx @@ -15,6 +15,7 @@ import { NPopover, NCard } from 'naive-ui' import RayIcon from '@/components/RayIcon/index' import type { TableSettingProvider } from '@/components/RayTable/src/type' +import type { ComponentSize } from '@/types/modules/component' const TableSize = defineComponent({ name: 'TableSize', diff --git a/src/components/RayTable/src/index.tsx b/src/components/RayTable/src/index.tsx index a173c244..fa6a903a 100644 --- a/src/components/RayTable/src/index.tsx +++ b/src/components/RayTable/src/index.tsx @@ -52,6 +52,7 @@ import type { WritableComputedRef } from 'vue' import type { DropdownOption } from 'naive-ui' import type { ExportExcelHeader } from '@use-utils/xlsx' import type { DataTableInst } from 'naive-ui' +import type { ComponentSize } from '@/types/modules/component' const RayTable = defineComponent({ name: 'RayTable', @@ -60,8 +61,8 @@ const RayTable = defineComponent({ setup(props, { emit, expose }) { const rayTableInstance = ref() - const tableUUID = uuid() // 表格 id, 用于打印表格 - const rayTableUUID = uuid() // RayTable id, 用于全屏表格 + const tableUUID = uuid(16) // 表格 id, 用于打印表格 + const rayTableUUID = uuid(16) // RayTable id, 用于全屏表格 const modelRightClickMenu = computed(() => props.rightClickMenu) const modelColumns = computed({ get: () => props.columns, diff --git a/src/components/RayTable/src/type.ts b/src/components/RayTable/src/type.ts index 296d6669..65dd12d3 100644 --- a/src/components/RayTable/src/type.ts +++ b/src/components/RayTable/src/type.ts @@ -7,6 +7,7 @@ import type { DataTableInst, } from 'naive-ui' import type { ComputedRef, WritableComputedRef, VNode } from 'vue' +import type { ComponentSize } from '@/types/modules/component' export interface ActionOptions extends DataTableBaseColumn { leftFixedActivated?: boolean // 向左固定 diff --git a/src/directives/modules/debounce/index.ts b/src/directives/modules/debounce/index.ts index 86af2fac..7101bf48 100644 --- a/src/directives/modules/debounce/index.ts +++ b/src/directives/modules/debounce/index.ts @@ -19,6 +19,7 @@ import { on, off } from '@use-utils/element' import type { Directive } from 'vue' import type { DebounceBindingOptions } from './type' +import type { AnyFunc } from '@/types/modules/utils' let debounceFunction: AnyFunc | null diff --git a/src/directives/modules/debounce/type.ts b/src/directives/modules/debounce/type.ts index bb14fda5..25aa981d 100644 --- a/src/directives/modules/debounce/type.ts +++ b/src/directives/modules/debounce/type.ts @@ -1,4 +1,5 @@ import type { DebounceSettings } from 'lodash-es' +import type { AnyFunc } from '@/types/modules/utils' export interface DebounceBindingOptions { func: AnyFunc diff --git a/src/directives/modules/throttle/index.ts b/src/directives/modules/throttle/index.ts index 4e29b6a6..c6f632bb 100644 --- a/src/directives/modules/throttle/index.ts +++ b/src/directives/modules/throttle/index.ts @@ -19,6 +19,7 @@ import { on, off } from '@use-utils/element' import type { Directive } from 'vue' import type { ThrottleBindingOptions } from './type' +import type { AnyFunc } from '@/types/modules/utils' let throttleFunction: AnyFunc | null diff --git a/src/directives/modules/throttle/type.ts b/src/directives/modules/throttle/type.ts index 7620c19b..9d8c36c7 100644 --- a/src/directives/modules/throttle/type.ts +++ b/src/directives/modules/throttle/type.ts @@ -1,4 +1,5 @@ import type { ThrottleSettings } from 'lodash-es' +import type { AnyFunc } from '@/types/modules/utils' export interface ThrottleBindingOptions { func: AnyFunc diff --git a/src/icons/language.svg b/src/icons/language.svg index cd6e9aa9..b399fdcb 100644 --- a/src/icons/language.svg +++ b/src/icons/language.svg @@ -1,3 +1,6 @@ - - + + \ No newline at end of file diff --git a/src/layout/components/Menu/index.tsx b/src/layout/components/Menu/index.tsx index 20e655c1..3bc1f9a5 100644 --- a/src/layout/components/Menu/index.tsx +++ b/src/layout/components/Menu/index.tsx @@ -8,6 +8,7 @@ import { MENU_COLLAPSED_CONFIG, MENU_ACCORDION } from '@/appConfig/appConfig' import { useVueRouter } from '@/router/helper/useVueRouter' import type { MenuInst } from 'naive-ui' +import type { NaiveMenuOptions } from '@/types/modules/component' const LayoutMenu = defineComponent({ name: 'LayoutMenu', diff --git a/src/layout/components/MenuTag/index.scss b/src/layout/components/MenuTag/index.scss index 07393ca1..d7238a22 100644 --- a/src/layout/components/MenuTag/index.scss +++ b/src/layout/components/MenuTag/index.scss @@ -34,8 +34,6 @@ $menuTagWrapperWidth: 76px; & .menu-tag__right-setting { width: 28px; height: 20px; - // display: inline-flex; - // align-items: center; } } } diff --git a/src/layout/components/MenuTag/index.tsx b/src/layout/components/MenuTag/index.tsx index a70fbf3e..e068c7d1 100644 --- a/src/layout/components/MenuTag/index.tsx +++ b/src/layout/components/MenuTag/index.tsx @@ -36,6 +36,7 @@ import { ROOT_ROUTE } from '@/appConfig/appConfig' import { getElement } from '@use-utils/element' import type { MenuOption, ScrollbarInst } from 'naive-ui' +import type { MenuTagOptions } from '@/types/modules/app' const MenuTag = defineComponent({ name: 'MenuTag', @@ -148,7 +149,7 @@ const MenuTag = defineComponent({ disabled: false, }, ]) - const scrollBarUUID = uuid() + const scrollBarUUID = uuid(16) const actionMap = { reloadCurrentPage: () => { changeSwitcher(false, 'reloadRouteSwitch') @@ -380,7 +381,9 @@ const MenuTag = defineComponent({ /** 动态更新 menu tag 所在位置 */ const positionMenuTag = () => { nextTick().then(() => { - const tags = getElement(`attr:${MENU_TAG_DATA}="${menuKey.value}"`) + const tags = getElement( + `attr:${MENU_TAG_DATA}="${menuKey.value}"`, + ) if (tags?.length) { const [menuTag] = tags @@ -505,9 +508,9 @@ const MenuTag = defineComponent({ [this.MENU_TAG_DATA]: curr.path, }} > - {typeof curr.label === 'function' - ? curr.label() - : curr.label} + {typeof curr.label === 'string' + ? curr.label + : curr.label?.()} ))} diff --git a/src/layout/components/SiderBar/Components/GlobalSeach/index.tsx b/src/layout/components/SiderBar/Components/GlobalSeach/index.tsx index 3ace8804..6bb352d4 100644 --- a/src/layout/components/SiderBar/Components/GlobalSeach/index.tsx +++ b/src/layout/components/SiderBar/Components/GlobalSeach/index.tsx @@ -21,6 +21,7 @@ import { validMenuItemShow } from '@/router/helper/routerCopilot' import type { MenuOption } from 'naive-ui' import type { AppRouteMeta } from '@/router/type' +import type { AppMenuOption } from '@/types/modules/app' const GlobalSeach = defineComponent({ name: 'GlobalSeach', @@ -49,7 +50,7 @@ const GlobalSeach = defineComponent({ const modelMenuOptions = computed(() => menuStore.options) const state = reactive({ searchValue: null, - searchOptions: [] as IMenuOptions[], + searchOptions: [] as AppMenuOption[], }) const tiptextOptions = [ @@ -76,9 +77,9 @@ const GlobalSeach = defineComponent({ /** 根据输入值模糊检索菜单 */ const handleSearchMenuOptions = (value: string) => { - const arr: IMenuOptions[] = [] + const arr: AppMenuOption[] = [] - const filterArr = (options: IMenuOptions[]) => { + const filterArr = (options: AppMenuOption[]) => { options.forEach((curr) => { if (curr.children?.length) { filterArr(curr.children) diff --git a/src/layout/components/SiderBar/Components/SettingDrawer/index.tsx b/src/layout/components/SiderBar/Components/SettingDrawer/index.tsx index c9419890..1d1f82d9 100644 --- a/src/layout/components/SiderBar/Components/SettingDrawer/index.tsx +++ b/src/layout/components/SiderBar/Components/SettingDrawer/index.tsx @@ -16,6 +16,7 @@ import { useSetting } from '@/store' import { useI18n } from '@/locales/useI18n' import type { PropType } from 'vue' +import type { Placement } from '@/types/modules/component' const SettingDrawer = defineComponent({ name: 'SettingDrawer', @@ -25,7 +26,7 @@ const SettingDrawer = defineComponent({ default: false, }, placement: { - type: String as PropType, + type: String as PropType, default: 'right', }, width: { diff --git a/src/layout/components/SiderBar/index.tsx b/src/layout/components/SiderBar/index.tsx index b16643b2..60804127 100644 --- a/src/layout/components/SiderBar/index.tsx +++ b/src/layout/components/SiderBar/index.tsx @@ -29,12 +29,11 @@ import AppAvatar from '@/components/AppComponents/AppAvatar/index' import { useSetting } from '@/store' import { LOCAL_OPTIONS } from '@/appConfig/localConfig' import { useAvatarOptions, avatarDropdownClick } from './hook' -import { getCache } from '@/utils/cache' import screenfull from 'screenfull' import { useI18n } from '@/locales/useI18n' -import { APP_CATCH_KEY } from '@/appConfig/appConfig' import type { IconEventMapOptions, IconEventMap } from './type' +import type { SigninCallback } from '@/store/modules/signin/type' const SiderBar = defineComponent({ name: 'SiderBar', @@ -46,7 +45,6 @@ const SiderBar = defineComponent({ const { drawerPlacement, breadcrumbSwitch } = storeToRefs(settingStore) const showSettings = ref(false) - const signin = getCache(APP_CATCH_KEY.signin) const spaceItemStyle = { display: 'flex', } @@ -131,7 +129,6 @@ const SiderBar = defineComponent({ handleIconClick, showSettings, updateLocale, - signin, spaceItemStyle, drawerPlacement, breadcrumbSwitch, diff --git a/src/locales/helper.ts b/src/locales/helper.ts index 77d50eb3..e00dbef6 100644 --- a/src/locales/helper.ts +++ b/src/locales/helper.ts @@ -22,7 +22,7 @@ import { getCache } from '@use-utils/cache' import { SYSTEM_DEFAULT_LOCAL } from '@/appConfig/localConfig' import { APP_CATCH_KEY } from '@/appConfig/appConfig' -import type { Recordable } from '@/types/type-utils' +import type { Recordable } from '@/types/modules/helper' import type { AppLocalesModules, AppLocalesDropdownMixedOption, @@ -126,10 +126,12 @@ export const naiveLocales = (key: string) => { * @remak 未避免出现加载语言错误问题, 故而在 `main.ts` 注册时, 应优先加载 `i18n` 避免出现该问题 */ export const getDefaultLocal = () => { - const catchLanguage = getCache(APP_CATCH_KEY.localeLanguage, 'localStorage') + const catchLanguage = getCache( + APP_CATCH_KEY.localeLanguage, + 'localStorage', + ) - const locale: string = - catchLanguage !== 'no' ? catchLanguage : SYSTEM_DEFAULT_LOCAL + const locale = catchLanguage ? catchLanguage : SYSTEM_DEFAULT_LOCAL return locale } diff --git a/src/router/helper/permission.ts b/src/router/helper/permission.ts index 0bee3bb6..bca0982d 100644 --- a/src/router/helper/permission.ts +++ b/src/router/helper/permission.ts @@ -31,16 +31,17 @@ import type { NavigationGuardNext, RouteLocationNormalized, } from 'vue-router' +import type { AppMenuOption } from '@/types/modules/app' export const permissionRouter = (router: Router) => { const { beforeEach } = router beforeEach((to, from, next) => { - const token = getCache(APP_CATCH_KEY.token) - const route = getCache('menuKey') + const token = getCache(APP_CATCH_KEY.token) + const route = getCache('menuKey') || ROOT_ROUTE.path - if (token !== 'no') { - if (validMenuItemShow(to as unknown as IMenuOptions)) { + if (token !== null) { + if (validMenuItemShow(to as unknown as AppMenuOption)) { if (to.path === '/' || from.path === '/login') { if (route !== 'no') { next(route) diff --git a/src/router/helper/routerCopilot.ts b/src/router/helper/routerCopilot.ts index d514e15d..892bcac8 100644 --- a/src/router/helper/routerCopilot.ts +++ b/src/router/helper/routerCopilot.ts @@ -24,6 +24,7 @@ import { setCache } from '@/utils/cache' import type { Router } from 'vue-router' import type { AppRouteMeta } from '@/router/type' +import type { AppMenuOption } from '@/types/modules/app' /** * @@ -64,7 +65,7 @@ export const validRole = (meta: AppRouteMeta) => { * * 如果你仅仅是希望校验是否满足权限, 应该使用另一个方法 validRole */ -export const validMenuItemShow = (option: IMenuOptions) => { +export const validMenuItemShow = (option: AppMenuOption) => { const { meta, name } = option const hidden = meta?.hidden === undefined || meta?.hidden === false ? false : meta?.hidden diff --git a/src/router/modules/directive.ts b/src/router/modules/directive.ts index 8242957f..ffd65bc9 100644 --- a/src/router/modules/directive.ts +++ b/src/router/modules/directive.ts @@ -8,8 +8,8 @@ const directive: AppRouteRecordRaw = { component: () => import('@/views/directive/index'), meta: { i18nKey: t('menu.Directive'), - icon: 'rely', - order: 3, + icon: 'other', + order: 2, }, } diff --git a/src/router/modules/iframe.ts b/src/router/modules/iframe.ts index c36116ef..6fdf5064 100644 --- a/src/router/modules/iframe.ts +++ b/src/router/modules/iframe.ts @@ -7,7 +7,7 @@ const iframe: AppRouteRecordRaw = { name: 'IframeDemo', component: () => import('@/views/iframe/index'), meta: { - icon: 'rely', + icon: 'other', order: 2, noLocalTitle: 'iframe', }, diff --git a/src/router/modules/multi-menu.ts b/src/router/modules/multi-menu.ts index d7fe3228..565b4a91 100644 --- a/src/router/modules/multi-menu.ts +++ b/src/router/modules/multi-menu.ts @@ -10,7 +10,7 @@ const multiMenu: AppRouteRecordRaw = { component: LAYOUT, meta: { i18nKey: t('menu.MultiMenu'), - icon: 'table', + icon: 'other', order: 4, }, children: [ diff --git a/src/router/modules/precision.ts b/src/router/modules/precision.ts index ed1ba75f..bad283e6 100644 --- a/src/router/modules/precision.ts +++ b/src/router/modules/precision.ts @@ -8,7 +8,7 @@ const precision: AppRouteRecordRaw = { component: () => import('@/views/precision/index'), meta: { i18nKey: t('menu.CalculatePrecision'), - icon: 'rely', + icon: 'other', order: 2, }, } diff --git a/src/router/modules/table.ts b/src/router/modules/table.ts index 7a4d4168..809880c9 100644 --- a/src/router/modules/table.ts +++ b/src/router/modules/table.ts @@ -8,7 +8,7 @@ const table: AppRouteRecordRaw = { component: () => import('@/views/table/index'), meta: { i18nKey: t('menu.Table'), - icon: 'table', + icon: 'other', order: 2, }, } diff --git a/src/router/type.ts b/src/router/type.ts index 76333ecd..f1d6ad32 100644 --- a/src/router/type.ts +++ b/src/router/type.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { RouteRecordRaw } from 'vue-router' -import type { Recordable } from '@/types/type-utils' +import type { Recordable } from '@/types/modules/helper' import type { DefineComponent, VNode } from 'vue' export type Component = diff --git a/src/store/modules/keep-alive/index.ts b/src/store/modules/keep-alive/index.ts index 4d1d8f4d..e6e02fd5 100644 --- a/src/store/modules/keep-alive/index.ts +++ b/src/store/modules/keep-alive/index.ts @@ -21,6 +21,7 @@ import { APP_KEEP_ALIVE } from '@/appConfig/appConfig' import type { KeepAliveStoreState } from './type' +import type { AppMenuOption } from '@/types/modules/app' export const useKeepAlive = defineStore( 'keepAlive', @@ -40,7 +41,7 @@ export const useKeepAlive = defineStore( * @remark 判断当前页面是否配置需要缓存, 并且判断当前缓存数量是否超过最大缓存数设置数量 * @remark 如果超过最大阈值, 则会按照尾插头删方式维护该队列 */ - const setKeepAliveInclude = (option: IMenuOptions) => { + const setKeepAliveInclude = (option: AppMenuOption) => { const length = getCurrentKeepAliveLength() const { name, diff --git a/src/store/modules/menu/helper.ts b/src/store/modules/menu/helper.ts index 25dc478b..8c9cc594 100644 --- a/src/store/modules/menu/helper.ts +++ b/src/store/modules/menu/helper.ts @@ -13,10 +13,15 @@ import { MENU_COLLAPSED_CONFIG, ROOT_ROUTE } from '@/appConfig/appConfig' import RayIcon from '@/components/RayIcon/index' -import { validteValueType } from '@/utils/hook' +import { isValueType } from '@/utils/hook' import { getCache, setCache } from '@/utils/cache' import type { VNode } from 'vue' +import type { + AppMenuOption, + MenuTagOptions, + AppMenuKey, +} from '@/types/modules/app' /** * @@ -27,7 +32,7 @@ import type { VNode } from 'vue' * @remark 检查是否为所需项 */ const check = ( - node: IMenuOptions, + node: AppMenuOption, key: string | number, value: string | number, ) => { @@ -43,11 +48,11 @@ const check = ( * @remark 匹配所有节点 */ const process = ( - options: IMenuOptions, + options: AppMenuOption, key: string | number, value: string | number, ) => { - const temp: IMenuOptions[] = [] + const temp: AppMenuOption[] = [] // 检查当前节点是否匹配值 if (check(options, key, value)) { @@ -79,7 +84,7 @@ const process = ( * @param value 匹配值 */ export const parse = ( - options: IMenuOptions[], + options: AppMenuOption[], key: string | number, value: string | number, ) => { @@ -105,8 +110,8 @@ export const parse = ( * @remark 查找当前菜单项 */ export const matchMenuOption = ( - item: IMenuOptions, - key: MenuKey, + item: AppMenuOption, + key: AppMenuKey, menuTagOptions: MenuTagOptions[], ) => { if (item.path !== key) { @@ -125,7 +130,7 @@ export const matchMenuOption = ( * @remark 动态修改浏览器标题 * @remark 会自动拼接 sideBarLogo.title */ -export const updateDocumentTitle = (option: IMenuOptions) => { +export const updateDocumentTitle = (option: AppMenuOption) => { const { breadcrumbLabel } = option const { layout: { sideBarLogo }, @@ -135,14 +140,14 @@ export const updateDocumentTitle = (option: IMenuOptions) => { document.title = breadcrumbLabel + ' - ' + spliceTitle } -export const hasMenuIcon = (option: IMenuOptions) => { +export const hasMenuIcon = (option: AppMenuOption) => { const { meta } = option if (!meta.icon) { return } - if (validteValueType(meta.icon, 'Object')) { + if (isValueType(meta.icon, 'Object')) { return () => meta.icon } @@ -161,8 +166,10 @@ export const hasMenuIcon = (option: IMenuOptions) => { /** 获取缓存的 menu key, 如果未获取到则使用 ROOTROUTE path 当作默认激活路由菜单 */ export const getCatchMenuKey = () => { const { path: rootPath } = ROOT_ROUTE - const cacheMenuKey: MenuKey = - getCache('menuKey') === 'no' ? rootPath : getCache('menuKey') + const cacheMenuKey = + getCache('menuKey') === null + ? rootPath + : getCache('menuKey') return cacheMenuKey } diff --git a/src/store/modules/menu/index.ts b/src/store/modules/menu/index.ts index 2aff1676..d8130c28 100644 --- a/src/store/modules/menu/index.ts +++ b/src/store/modules/menu/index.ts @@ -40,6 +40,7 @@ import { useVueRouter } from '@/router/helper/useVueRouter' import type { MenuOption } from 'naive-ui' import type { AppRouteMeta } from '@/router/type' +import type { AppMenuOption, MenuTagOptions } from '@/types/modules/app' export const useMenu = defineStore( 'menu', @@ -51,10 +52,10 @@ export const useMenu = defineStore( const menuState = reactive({ menuKey: getCatchMenuKey(), // 当前菜单 `key` - options: [] as IMenuOptions[], // 菜单列表 + options: [] as AppMenuOption[], // 菜单列表 collapsed: false, // 是否折叠菜单 menuTagOptions: [] as MenuTagOptions[], // tag 标签菜单 - breadcrumbOptions: [] as IMenuOptions[], // 面包屑菜单 + breadcrumbOptions: [] as AppMenuOption[], // 面包屑菜单 }) /** @@ -65,7 +66,7 @@ export const useMenu = defineStore( * @remark 获取完整菜单项 */ const getCompleteRoutePath = ( - options: IMenuOptions[], + options: AppMenuOption[], key: string | number, ) => { const ops = parse(options, 'key', key) @@ -94,8 +95,8 @@ export const useMenu = defineStore( menuState.menuKey, menuState.menuTagOptions, ) - updateDocumentTitle(item as unknown as IMenuOptions) - setKeepAliveInclude(item as unknown as IMenuOptions) + updateDocumentTitle(item as unknown as AppMenuOption) + setKeepAliveInclude(item as unknown as AppMenuOption) menuState.breadcrumbOptions = parse(menuState.options, 'key', key) // 获取面包屑 @@ -168,7 +169,7 @@ export const useMenu = defineStore( * @remark 如果权限发生变动, 则会触发强制弹出页面并且重新登陆 */ const setupAppRoutes = () => { - const resolveOption = (option: IMenuOptions) => { + const resolveOption = (option: AppMenuOption) => { const { meta } = option /** 设置 label, i18nKey 优先级最高 */ @@ -184,9 +185,9 @@ export const useMenu = defineStore( default: () => label.value, }), breadcrumbLabel: label.value, - } as IMenuOptions + } as AppMenuOption /** 合并 icon */ - const attr: IMenuOptions = Object.assign({}, route, { + const attr: AppMenuOption = Object.assign({}, route, { icon: hasMenuIcon(option), }) @@ -203,8 +204,8 @@ export const useMenu = defineStore( return attr } - const resolveRoutes = (routes: IMenuOptions[], index: number) => { - const catchArr: IMenuOptions[] = [] + const resolveRoutes = (routes: AppMenuOption[], index: number) => { + const catchArr: AppMenuOption[] = [] for (const curr of routes) { if (curr.children?.length && validMenuItemShow(curr)) { @@ -221,7 +222,7 @@ export const useMenu = defineStore( } /** 缓存菜单列表 */ - menuState.options = resolveRoutes(routeModules as IMenuOptions[], 0) + menuState.options = resolveRoutes(routeModules as AppMenuOption[], 0) /** 初始化后渲染面包屑 */ nextTick(() => { diff --git a/src/store/modules/setting/index.ts b/src/store/modules/setting/index.ts index 57f359f5..bc17ef60 100644 --- a/src/store/modules/setting/index.ts +++ b/src/store/modules/setting/index.ts @@ -6,7 +6,7 @@ import { useI18n } from '@/locales/useI18n' import { APP_NAIVE_UI_THEME_OVERRIDES } from '@/appConfig/designConfig' import { useDayjs } from '@/dayjs/index' -import type { ConditionalPick } from '@/types/type-utils' +import type { ConditionalPick } from '@/types/modules/helper' import type { SettingState } from '@/store/modules/setting/type' import type { DayjsLocal } from '@/dayjs/type' diff --git a/src/store/modules/setting/type.ts b/src/store/modules/setting/type.ts index 76efce46..c6130880 100644 --- a/src/store/modules/setting/type.ts +++ b/src/store/modules/setting/type.ts @@ -1,7 +1,8 @@ import type { GlobalThemeOverrides } from 'naive-ui' +import type { Placement } from '@/types/modules/component' export interface SettingState { - drawerPlacement: NaiveDrawerPlacement + drawerPlacement: Placement primaryColorOverride: GlobalThemeOverrides themeValue: boolean reloadRouteSwitch: boolean diff --git a/src/types/module.d.ts b/src/types/app.d.ts similarity index 100% rename from src/types/module.d.ts rename to src/types/app.d.ts diff --git a/src/types/axios.d.ts b/src/types/axios.d.ts deleted file mode 100644 index 6260e6da..00000000 --- a/src/types/axios.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -export {} - -declare global { - /** - * - * 请求响应体类型 - * - * 可以根据自己实际情况更改 - */ - declare interface AxiosResponseBody { - data: T - message: string - code: number - } -} diff --git a/src/types/cache.d.ts b/src/types/cache.d.ts deleted file mode 100644 index dad41285..00000000 --- a/src/types/cache.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export {} - -declare global { - declare type CacheType = 'sessionStorage' | 'localStorage' -} diff --git a/src/types/component.d.ts b/src/types/component.d.ts deleted file mode 100644 index 96056665..00000000 --- a/src/types/component.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -export {} - -import type { ECharts } from 'echarts/core' -import type { - MessageApi, - DialogApi, - LoadingBarApi, - NotificationApi, - MenuOption, - MenuDividerOption, - MenuGroupOption, -} from 'naive-ui' -import type { VNodeChild } from 'vue' - -declare global { - declare type ComponentSize = 'small' | 'medium' | 'large' - - declare type EChartsInstance = ECharts - - declare type NaiveDrawerPlacement = 'top' | 'right' | 'bottom' | 'left' - - declare type NaiveMenuOptions = - | MenuOption - | MenuDividerOption - | MenuGroupOption -} diff --git a/src/types/index.d.ts b/src/types/global.d.ts similarity index 87% rename from src/types/index.d.ts rename to src/types/global.d.ts index c7451895..c2bade79 100644 --- a/src/types/index.d.ts +++ b/src/types/global.d.ts @@ -1,14 +1,17 @@ -export {} - +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { AppConfig } from './cfg' import type { MessageApi, DialogApi, LoadingBarApi, NotificationApi, } from 'naive-ui' -import type { AppConfig } from './cfg' -export global { +declare global { + declare interface UnknownObjectKey { + [propName: string]: any + } + declare const __APP_CFG__: AppConfig declare interface Window { @@ -41,9 +44,9 @@ export global { $loadingBar: LoadingBarApi $notification: NotificationApi - // eslint-disable-next-line @typescript-eslint/no-explicit-any DocsAPI?: any - // eslint-disable-next-line @typescript-eslint/no-explicit-any DocEditor?: any + + msCrypto: Crypto } } diff --git a/src/types/micro.d.ts b/src/types/micro.d.ts deleted file mode 100644 index ab56ba7f..00000000 --- a/src/types/micro.d.ts +++ /dev/null @@ -1,163 +0,0 @@ -export {} - -declare global { - export declare type lifecycle = (appWindow: Window) => unknown - export declare type loadErrorHandler = (url: string, e: Error) => unknown - - export declare type baseOptions = { - /** 唯一性用户必须保证 */ - name: string - /** 需要渲染的url */ - url: string - /** 代码替换钩子 */ - replace?: (code: string) => string - /** 自定义fetch */ - fetch?: (input: RequestInfo, init?: RequestInit) => Promise - /** 注入给子应用的属性 */ - props?: { [key: string]: unknown } - /** 自定义iframe属性 */ - attrs?: { [key: string]: unknown } - /** 子应用采用fiber模式执行 */ - fiber?: boolean - /** 子应用保活,state不会丢失 */ - alive?: boolean - /** 子应用采用降级iframe方案 */ - degrade?: boolean - /** 子应用插件 */ - plugins?: Array - /** 子应用生命周期 */ - beforeLoad?: lifecycle - beforeMount?: lifecycle - afterMount?: lifecycle - beforeUnmount?: lifecycle - afterUnmount?: lifecycle - activated?: lifecycle - deactivated?: lifecycle - loadError?: loadErrorHandler - } - - export declare type preOptions = baseOptions & { - /** 预执行 */ - exec?: boolean - } - - export declare type startOptions = baseOptions & { - /** 渲染的容器 */ - el: HTMLElement | string - /** - * 路由同步开关 - * 如果false,子应用跳转主应用路由无变化,但是主应用的history还是会增加 - * https://html.spec.whatwg.org/multipage/history.html#the-history-interface - */ - sync?: boolean - /** 子应用短路径替换,路由同步时生效 */ - prefix?: { [key: string]: string } - /** 子应用加载时loading元素 */ - loading?: HTMLElement - } - - export declare type optionProperty = 'url' | 'el' - - /** - * 合并 preOptions 和 startOptions,并且将 url 和 el 变成可选 - */ - export declare type cacheOptions = Omit< - preOptions & startOptions, - optionProperty - > & - Partial> - - export declare type startOption = { - /** 唯一性用户必须保证 */ - name: string - /** 需要渲染的url */ - url: string - /** 渲染的容器 */ - el: HTMLElement | string - /** 子应用加载时loading元素 */ - loading?: HTMLElement - /** 路由同步开关, false刷新无效,但是前进后退依然有效 */ - sync?: boolean - /** 子应用短路径替换,路由同步时生效 */ - prefix?: { [key: string]: string } - /** 子应用保活模式,state不会丢失 */ - alive?: boolean - /** 注入给子应用的数据 */ - props?: { [key: string]: unknown } - /** js采用fiber模式执行 */ - fiber?: boolean - /** 子应用采用降级iframe方案 */ - degrade?: boolean - /** 自定义iframe属性 */ - attrs?: { [key: string]: unknown } - /** 代码替换钩子 */ - replace?: (codeText: string) => string - /** 自定义fetch,资源和接口 */ - fetch?: (input: RequestInfo, init?: RequestInit) => Promise - /** 子应插件 */ - plugins: Array - /** 子应用生命周期 */ - beforeLoad?: lifecycle - /** 没有做生命周期改造的子应用不会调用 */ - beforeMount?: lifecycle - afterMount?: lifecycle - beforeUnmount?: lifecycle - afterUnmount?: lifecycle - /** 非保活应用不会调用 */ - activated?: lifecycle - deactivated?: lifecycle - /** 子应用资源加载失败后调用 */ - loadError?: loadErrorHandler - } - - export declare type preOptions = { - /** 唯一性用户必须保证 */ - name: string - /** 需要渲染的url */ - url: string - /** 注入给子应用的数据 */ - props?: { [key: string]: unknown } - /** 自定义iframe属性 */ - attrs?: { [key: string]: unknown } - /** 代码替换钩子 */ - replace?: (code: string) => string - /** 自定义fetch,资源和接口 */ - fetch?: (input: RequestInfo, init?: RequestInit) => Promise - /** 子应用保活模式,state不会丢失 */ - alive?: boolean - /** 预执行模式 */ - exec?: boolean - /** js采用fiber模式执行 */ - fiber?: boolean - /** 子应用采用降级iframe方案 */ - degrade?: boolean - /** 子应插件 */ - plugins: Array - /** 子应用生命周期 */ - beforeLoad?: lifecycle - /** 没有做生命周期改造的子应用不会调用 */ - beforeMount?: lifecycle - afterMount?: lifecycle - beforeUnmount?: lifecycle - afterUnmount?: lifecycle - /** 非保活应用不会调用 */ - activated?: lifecycle - deactivated?: lifecycle - /** 子应用资源加载失败后调用 */ - loadError?: loadErrorHandler - } - - export declare class EventBus { - private id - private eventObj - constructor(id: string) - $on(event: string, fn: Function): EventBus - /** 任何$emit都会导致监听函数触发,第一个参数为事件名,后续的参数为$emit的参数 */ - $onAll(fn: (event: string, ...args: Array) => unknown): EventBus - $once(event: string, fn: Function): void - $off(event: string, fn: Function): EventBus - $offAll(fn: Function): EventBus - $emit(event: string, ...args: Array): EventBus - $clear(): EventBus - } -} diff --git a/src/types/modules/app.ts b/src/types/modules/app.ts new file mode 100644 index 00000000..7d2122c3 --- /dev/null +++ b/src/types/modules/app.ts @@ -0,0 +1,21 @@ +import type { VNode } from 'vue' +import type { AppRouteRecordRaw, AppRouteMeta } from '@/router/type' + +export type Key = string | number + +export interface AppMenuOption extends AppRouteRecordRaw { + name: string + key: Key + path: string + label: string | (() => VNode) + show?: boolean + children?: AppMenuOption[] + meta: AppRouteMeta + breadcrumbLabel?: string +} + +export interface MenuTagOptions extends AppMenuOption { + closeable?: boolean +} + +export type AppMenuKey = Key | null diff --git a/src/types/appConfig.ts b/src/types/modules/appConfig.ts similarity index 100% rename from src/types/appConfig.ts rename to src/types/modules/appConfig.ts diff --git a/src/types/modules/axios.ts b/src/types/modules/axios.ts new file mode 100644 index 00000000..ad25f258 --- /dev/null +++ b/src/types/modules/axios.ts @@ -0,0 +1,5 @@ +export interface AxiosResponseBody { + data: T + message: string + code: number +} diff --git a/src/types/cfg.ts b/src/types/modules/cfg.ts similarity index 96% rename from src/types/cfg.ts rename to src/types/modules/cfg.ts index d61c1503..91b54f53 100644 --- a/src/types/cfg.ts +++ b/src/types/modules/cfg.ts @@ -5,6 +5,7 @@ import type { AliasOptions, UserConfigExport, } from 'vite' +import type { Recordable } from '@/types/modules/helper' export interface LayoutSideBarLogo { icon?: string @@ -49,8 +50,6 @@ export interface Config { appPrimaryColor?: AppPrimaryColor } -export type Recordable = Record - /** * * 全局注入配置 diff --git a/src/types/modules/component.ts b/src/types/modules/component.ts new file mode 100644 index 00000000..e9fc9b12 --- /dev/null +++ b/src/types/modules/component.ts @@ -0,0 +1,10 @@ +import type { ECharts } from 'echarts/core' +import type { MenuOption, MenuDividerOption, MenuGroupOption } from 'naive-ui' + +export type ComponentSize = 'small' | 'medium' | 'large' + +export type EChartsInstance = ECharts + +export type Placement = 'top' | 'right' | 'bottom' | 'left' + +export type NaiveMenuOptions = MenuOption | MenuDividerOption | MenuGroupOption diff --git a/src/types/type-utils.ts b/src/types/modules/helper.ts similarity index 100% rename from src/types/type-utils.ts rename to src/types/modules/helper.ts diff --git a/src/types/modules/utils.ts b/src/types/modules/utils.ts new file mode 100644 index 00000000..b39a45ce --- /dev/null +++ b/src/types/modules/utils.ts @@ -0,0 +1,44 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type CryptoJS from 'crypto-js' + +export type CacheType = 'sessionStorage' | 'localStorage' + +export type EventListenerOrEventListenerObject = + | EventListener + | EventListenerObject + +export type ValidteValueType = + | 'Object' + | 'Undefined' + | 'Null' + | 'Boolean' + | 'Number' + | 'String' + | 'Symbol' + | 'Function' + | 'Date' + | 'Array' + | 'RegExp' + | 'Map' + | 'Set' + | 'WeakMap' + | 'WeakSet' + | 'ArrayBuffer' + | 'DataView' + | 'Int8Array' + | 'Uint8Array' + | 'Uint8ClampedArray' + | 'Int16Array' + | 'Uint16Array' + | 'Int32Array' + | 'Uint32Array' + | 'Float32Array' + | 'Float64Array' + +export type WordArray = CryptoJS.lib.WordArray + +export type CipherParams = CryptoJS.lib.CipherParams + +export type AnyFunc = (...args: any[]) => any + +export type AnyVoidFunc = (...args: any[]) => void diff --git a/src/types/store.d.ts b/src/types/store.d.ts deleted file mode 100644 index 771f57fa..00000000 --- a/src/types/store.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -export {} - -import type { RouteRecordRaw, RouteMeta } from 'vue-router' -import type { MenuOption } from 'naive-ui' -import type { VNode } from 'vue' -import type { AppRouteRecordRaw, AppRouteMeta } from '@/router/type' - -declare global { - declare interface IMenuOptions extends AppRouteRecordRaw, MenuOption { - name: string - key: string | number - path: string - label: string | Function - show?: boolean - children?: IMenuOptions[] - meta: AppRouteMeta - breadcrumbLabel?: string - noLocalTitle?: string | number - } - - declare interface MenuTagOptions extends IMenuOptions { - closeable?: boolean - } - - declare type MenuKey = null | string | number -} diff --git a/src/types/utils.d.ts b/src/types/utils.d.ts deleted file mode 100644 index ec1ced62..00000000 --- a/src/types/utils.d.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -export {} - -import type CryptoJS from 'crypto-js' -import type { VNodeChild } from 'vue' - -export global { - declare interface UnknownObjectKey { - [propName: string]: any - } - - declare type EventListenerOrEventListenerObject = - | EventListener - | EventListenerObject - - declare type ValidteValueType = - | 'Number' - | 'String' - | 'Boolean' - | 'Object' - | 'Function' - | 'Null' - | 'Undefined' - | 'Array' - | 'Date' - | 'Math' - | 'RegExp' - | 'Error' - - declare type WordArray = CryptoJS.lib.WordArray - - declare type CipherOption = CryptoJS.lib.CipherOption - - declare type CipherParams = CryptoJS.lib.CipherParams - - declare type VoidFunc = (...args: any[]) => void - - declare type AnyFunc = (...args: any[]) => any -} diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 4dd34cdf..1bc9094e 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -11,6 +11,8 @@ /** vue3 项目里建议直接用 vueuse useStorage 方法 */ +import type { CacheType } from '@/types/modules/utils' + /** * * @param key 需要设置的key @@ -32,16 +34,17 @@ export const setCache = ( * * @param key 需要获取目标缓存的key * @returns 获取缓存值 - * - * @remark 如果未匹配到目标值则返回字符串 'no' */ -export const getCache = (key: string, type: CacheType = 'sessionStorage') => { +export const getCache = ( + key: string, + type: CacheType = 'sessionStorage', +): T | null => { const data = type === 'localStorage' ? window.localStorage.getItem(key) : window.sessionStorage.getItem(key) - return Object.is(data, null) ? 'no' : JSON.parse(data as string) + return Object.is(data, null) ? null : JSON.parse(data as string) } /** diff --git a/src/utils/crypto.ts b/src/utils/crypto.ts index cb2d112f..3e1aa7e6 100644 --- a/src/utils/crypto.ts +++ b/src/utils/crypto.ts @@ -1,8 +1,10 @@ -import HmacSHA256 from 'crypto-js/hmac-sha256' -import SHA256 from 'crypto-js/sha256' -import AES from 'crypto-js/aes' -import MD5 from 'crypto-js/md5' -import BASE64 from 'crypto-js/enc-base64' +// import HmacSHA256 from 'crypto-js/hmac-sha256' +// import SHA256 from 'crypto-js/sha256' +// import AES from 'crypto-js/aes' +// import MD5 from 'crypto-js/md5' +// import BASE64 from 'crypto-js/enc-base64' + +// import type { WordArray, CipherParams } from '@/types/modules/utils' /** * @@ -11,118 +13,3 @@ import BASE64 from 'crypto-js/enc-base64' * * 手动补上官网地址: http://github.com/brix/crypto-js */ - -/** - * - * @param message 待加密信息 - * @param key 加密key - * - * @remark HmacSHA256 加密 - */ -export const useHmacSHA256 = ( - message: WordArray | string, - key: WordArray | string, -) => { - return new Promise((resolve) => { - const cry = HmacSHA256(message, key) - - resolve(cry) - }) -} - -/** - * - * @param message 待加密信息 - * - * @remark SHA256 加密 - */ -export const useSHA256 = (message: WordArray | string) => { - return new Promise((resolve) => { - const cry = SHA256(message) - - resolve(cry) - }) -} - -/** - * - * @param message 待加密信息 - * @param key 加密key - * @param cfg 加密配置信息 - * - * @remark AES 加密 - */ -export const useAESEncrypt = ( - message: WordArray | string, - key: WordArray | string, - cfg?: CipherOption, -) => { - return new Promise((resolve) => { - const cry = AES.encrypt(message, key, cfg) - - resolve(cry) - }) -} - -/** - * - * @param ciphertext 待解密信息 - * @param key 解密key - * @param cfg 解密配置信息 - * - * @remark AES 解密 - */ -export const useAESDecrypt = ( - ciphertext: CipherParams | string, - key: WordArray | string, - cfg?: CipherOption, -) => { - return new Promise((resolve) => { - const cry = AES.decrypt(ciphertext, key, cfg) - - resolve(cry) - }) -} - -/** - * - * @param message 待加密信息 - * @param cfg md5 加密配置 - * - * @remark md5 加密 - */ -export const useMD5 = (message: WordArray | string, cfg?: object) => { - return new Promise((resolve) => { - const cry = MD5(message, cfg) - - resolve(cry) - }) -} - -/** - * - * @param wordArray 待转为 base64 信息 - * - * @remark base64 加密 - */ -export const useBase64Stringify = (wordArray: WordArray) => { - return new Promise((resolve) => { - const cry = BASE64.stringify(wordArray) - - resolve(cry) - }) -} - -/** - * - * @param str 待转为 base64 信息 - * - * @remark base64 解密 - */ -export const useBase64Parse = (str: string) => { - return new Promise((resolve) => { - const cry = BASE64.parse(str) - - resolve(cry) - }) -} diff --git a/src/utils/element.ts b/src/utils/element.ts index 72fc1ae6..6145efbd 100644 --- a/src/utils/element.ts +++ b/src/utils/element.ts @@ -1,11 +1,14 @@ -import { validteValueType } from '@use-utils/hook' +import { isValueType } from '@use-utils/hook' import { ELEMENT_UNIT } from '@/appConfig/regConfig' +import type { EventListenerOrEventListenerObject } from '@/types/modules/utils' + /** * * @param element Target element dom * @param event 绑定事件类型 * @param handler 事件触发方法 + * @param useCapture 是否冒泡 * * @remark 给元素绑定某个事件柄方法 */ @@ -13,7 +16,7 @@ export const on = ( element: HTMLElement | Document | Window, event: string, handler: EventListenerOrEventListenerObject, - useCapture = false, + useCapture: boolean | AddEventListenerOptions = false, ) => { if (element && event && handler) { element.addEventListener(event, handler, useCapture) @@ -25,6 +28,7 @@ export const on = ( * @param element Target element dom * @param event 卸载事件类型 * @param handler 所需卸载方法 + * @param useCapture 是否冒泡 * * @remark 卸载元素上某个事件柄方法 */ @@ -32,7 +36,7 @@ export const off = ( element: HTMLElement | Document | Window, event: string, handler: EventListenerOrEventListenerObject, - useCapture = false, + useCapture: boolean | AddEventListenerOptions = false, ) => { if (element && event && handler) { element.removeEventListener(event, handler, useCapture) @@ -133,12 +137,12 @@ export const addStyle = ( styles: string | Partial, ) => { if (el) { - if (validteValueType(styles, 'Object')) { + if (isValueType(styles, 'Object')) { Object.keys(styles).forEach((item) => { el.style[item] = styles[item] }) - } else if (validteValueType(styles, 'String')) { - const _styles = styles as string + } else if (isValueType(styles, 'String')) { + const _styles = styles _styles.split(';').forEach((item) => { const [_k, _v] = item.split(':') @@ -223,9 +227,9 @@ export const colorToRgba = (color: string, alpha = 1) => { * 或者可以这样写 * const el = getElement('attr:type') */ -export const getElement = (element: string) => { +export const getElement = (element: string) => { if (!element) { - return + return null } let queryParam: string @@ -237,7 +241,7 @@ export const getElement = (element: string) => { } try { - const el = Array.from(document.querySelectorAll(queryParam)) + const el = Array.from(document.querySelectorAll(queryParam)) return el } catch (e) { @@ -248,15 +252,16 @@ export const getElement = (element: string) => { /** * * @param size css size + * @param unit 自动填充 css 尺寸单位 * * @remark 自动补全尺寸 */ -export const completeSize = (size: number | string) => { +export const completeSize = (size: number | string, unit = 'px') => { if (typeof size === 'number') { - return size.toString() + 'px' - } else if (ELEMENT_UNIT.test(size)) { + return size.toString() + unit + } else if (isValueType(size, 'String') && ELEMENT_UNIT.test(size)) { return size } else { - return size + 'px' + return size + unit } } diff --git a/src/utils/hook.ts b/src/utils/hook.ts index e516c499..1cecf4ef 100644 --- a/src/utils/hook.ts +++ b/src/utils/hook.ts @@ -1,3 +1,5 @@ +import type { ValidteValueType } from '@/types/modules/utils' + /** * * @returns 获取当前项目环境 @@ -14,9 +16,11 @@ export const getAppEnvironment = () => { * * @returns formate binary to base64 of the image */ -export const useImagebufferToBase64 = ( - data: ArrayBufferLike | ArrayLike, -) => { +export const arrayBufferToBase64Image = (data: ArrayBuffer): string | null => { + if (!data || data.byteLength) { + return null + } + const base64 = 'data:image/png;base64,' + window.btoa( @@ -34,10 +38,10 @@ export const useImagebufferToBase64 = ( * @param value 目标值 * @param type 类型 */ -export const validteValueType = ( - value: T, +export const isValueType = ( + value: unknown, type: ValidteValueType, -) => { +): value is T => { const valid = Object.prototype.toString.call(value) return valid.includes(type) @@ -49,35 +53,29 @@ export const validteValueType = ( * @param radix `uuid` 基数 * @returns `uuid` */ -export const uuid = (length = 16, radix?: number) => { - const sad = +export const uuid = (length = 16, radix = 62) => { + // 定义可用的字符集,即 0-9, A-Z, a-z + const availableChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('') + // 定义存储随机字符串的数组 const arr: string[] = [] + // 获取加密对象,兼容 IE11 + const cryptoObj = window.crypto || window.msCrypto let i = 0 - radix = radix || sad.length + // 循环 length 次,生成随机字符,并添加到数组中 + for (i = 0; i < length; i++) { + // 生成一个随机数 + const randomValues = new Uint32Array(1) - if (length) { - for (i = 0; i < length; i++) { - arr[i] = sad[0 | (Math.random() * radix)] - } - } else { - let r + cryptoObj.getRandomValues(randomValues) - arr[23] = '-' - arr[18] = arr[23] - arr[13] = arr[18] - arr[8] = arr[13] - arr[14] = '4' + // 根据随机数生成对应的字符,并添加到数组中 + const index = randomValues[0] % radix - for (i = 0; i < 36; i++) { - if (!arr[i]) { - r = 0 | (Math.random() * radix) - - arr[i] = sad[i === 19 ? (r & 0x3) | 0x8 : r] - } - } + arr.push(availableChars[index]) } + // 将数组中的字符连接起来,返回最终的字符串 return arr.join('') } diff --git a/src/utils/precision.ts b/src/utils/precision.ts index 909a2f56..7162b67a 100644 --- a/src/utils/precision.ts +++ b/src/utils/precision.ts @@ -32,6 +32,7 @@ import currency from 'currency.js' import { cloneDeep } from 'lodash-es' import type { Options } from 'currency.js' +import type { AnyFunc } from '@/types/modules/utils' export type CurrencyArguments = string | number | currency diff --git a/src/views/axios/index.tsx b/src/views/axios/index.tsx index f202a5e3..cf313123 100644 --- a/src/views/axios/index.tsx +++ b/src/views/axios/index.tsx @@ -10,6 +10,7 @@ import { NButton, } from 'naive-ui' import { onAxiosTest } from '@use-api/test' +import { isArray } from 'lodash-es' const Axios = defineComponent({ name: 'RAxios', diff --git a/src/views/directive/index.tsx b/src/views/directive/index.tsx index bb794922..1bf76616 100644 --- a/src/views/directive/index.tsx +++ b/src/views/directive/index.tsx @@ -20,7 +20,7 @@ import { NFormItem, } from 'naive-ui' -import type { ConditionalPick } from '@/types/type-utils' +import type { ConditionalPick } from '@/types/modules/helper' const RDirective = defineComponent({ name: 'RDirective', diff --git a/src/views/echart/index.tsx b/src/views/echart/index.tsx index b70f6158..c41c67be 100644 --- a/src/views/echart/index.tsx +++ b/src/views/echart/index.tsx @@ -3,6 +3,8 @@ import './index.scss' import { NCard, NSwitch, NSpace, NP, NH6, NH2, NH3 } from 'naive-ui' import RayChart from '@/components/RayChart/index' +import type { EChartsInstance } from '@/types/modules/component' + const Echart = defineComponent({ name: 'REchart', setup() { diff --git a/src/views/iframe/index.tsx b/src/views/iframe/index.tsx index 160a1679..f559044d 100644 --- a/src/views/iframe/index.tsx +++ b/src/views/iframe/index.tsx @@ -17,7 +17,7 @@ * 做了简单的一个组件封装, 希望有用 */ -import { NSpace } from 'naive-ui' +import { NCard, NSpace } from 'naive-ui' import RayIframe from '@/components/RayIframe/index' const IframeDemo = defineComponent({ @@ -28,18 +28,20 @@ const IframeDemo = defineComponent({ render() { return ( - -

naive ui

+ - - -

vueuse

- -
+
+ + + ) }, diff --git a/src/views/office/views/document/index.tsx b/src/views/office/views/document/index.tsx index c2de0d8b..f2907266 100644 --- a/src/views/office/views/document/index.tsx +++ b/src/views/office/views/document/index.tsx @@ -16,7 +16,7 @@ import type { PropType } from 'vue' const Document = defineComponent({ name: 'RDocument', setup() { - const editorUUID = uuid() + const editorUUID = uuid(16) const state = reactive({}) const config = { document: { @@ -34,16 +34,6 @@ const Document = defineComponent({ }, } - const registerEdtior = () => { - const uid = uuid(12) - } - - onMounted(() => { - nextTick(() => { - registerEdtior() - }) - }) - return { ...toRefs(state), editorUUID, diff --git a/tsconfig.json b/tsconfig.json index f69c26eb..08bc3c13 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -47,6 +47,7 @@ "src/*.vue", "src/*", "components.d.ts", - "auto-imports.d.ts" + "auto-imports.d.ts", + "src/types/global.d.ts" ] } diff --git a/vite.config.ts b/vite.config.ts index ebff6388..0a3bebac 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,7 +7,6 @@ import { viteVueI18nPlugin, viteSVGIcon, } from './vite-plugin/index' - import viteVueJSX from '@vitejs/plugin-vue-jsx' import viteVeI18nPlugin from '@intlify/unplugin-vue-i18n/vite' import viteInspect from 'vite-plugin-inspect'