diff --git a/package.json b/package.json index 9f5eba8..aa3658c 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "vite-plugin-purge-icons": "^0.7.0", "vite-plugin-style-import": "^1.4.1", "vite-plugin-svg-icons": "^1.1.0", + "vite-plugin-vue-setup-extend": "^0.3.0", "vite-plugin-windicss": "^1.6.2", "vue-tsc": "^0.30.2", "windicss": "^3.4.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 10ea1b0..ea720eb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,7 +33,6 @@ specifiers: lodash-es: ^4.17.21 mockjs: ^1.1.0 nprogress: ^0.2.0 - path-to-regexp: ^6.2.0 pinia: ^2.0.9 postcss: ^8.4.5 postcss-html: ^1.3.0 @@ -54,6 +53,7 @@ specifiers: vite-plugin-purge-icons: ^0.7.0 vite-plugin-style-import: ^1.4.1 vite-plugin-svg-icons: ^1.1.0 + vite-plugin-vue-setup-extend: ^0.3.0 vite-plugin-windicss: ^1.6.2 vue: 3.2.26 vue-i18n: 9.1.9 @@ -74,7 +74,6 @@ dependencies: lodash-es: registry.nlark.com/lodash-es/4.17.21 mockjs: registry.npmmirror.com/mockjs/1.1.0 nprogress: registry.npmmirror.com/nprogress/0.2.0 - path-to-regexp: registry.npmmirror.com/path-to-regexp/6.2.0 pinia: registry.npmmirror.com/pinia/2.0.9_typescript@4.5.4+vue@3.2.26 qs: registry.npmmirror.com/qs/6.10.3 vue: registry.npmmirror.com/vue/3.2.26 @@ -125,6 +124,7 @@ devDependencies: vite-plugin-purge-icons: registry.nlark.com/vite-plugin-purge-icons/0.7.0_vite@2.7.10 vite-plugin-style-import: registry.npmmirror.com/vite-plugin-style-import/1.4.1_vite@2.7.10 vite-plugin-svg-icons: registry.npmmirror.com/vite-plugin-svg-icons/1.1.0_vite@2.7.10 + vite-plugin-vue-setup-extend: registry.npmmirror.com/vite-plugin-vue-setup-extend/0.3.0_vite@2.7.10 vite-plugin-windicss: registry.npmmirror.com/vite-plugin-windicss/1.6.2_vite@2.7.10 vue-tsc: registry.npmmirror.com/vue-tsc/0.30.2_typescript@4.5.4 windicss: registry.npmmirror.com/windicss/3.4.2 @@ -1732,7 +1732,7 @@ packages: { integrity: sha1-0t5eA0JOcH3BDHQGjd7a5wh0Gyc=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/eslint-utils/download/eslint-utils-2.1.0.tgz?cache=0&sync_timestamp=1631600361784&other_urls=https%3A%2F%2Fregistry.nlark.com%2Feslint-utils%2Fdownload%2Feslint-utils-2.1.0.tgz + tarball: https://registry.nlark.com/eslint-utils/download/eslint-utils-2.1.0.tgz } name: eslint-utils version: 2.1.0 @@ -4948,7 +4948,7 @@ packages: { integrity: sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz + tarball: https://registry.nlark.com/semver/download/semver-5.7.1.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-5.7.1.tgz } name: semver version: 5.7.1 @@ -4960,7 +4960,7 @@ packages: { integrity: sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.nlark.com/semver/download/semver-6.3.0.tgz + tarball: https://registry.nlark.com/semver/download/semver-6.3.0.tgz?cache=0&sync_timestamp=1631500167672&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-6.3.0.tgz } name: semver version: 6.3.0 @@ -7909,7 +7909,6 @@ packages: magic-string: registry.nlark.com/magic-string/0.25.7 postcss: registry.npmmirror.com/postcss/8.4.5 source-map: registry.nlark.com/source-map/0.6.1 - dev: false registry.npmmirror.com/@vue/compiler-ssr/3.2.26: resolution: @@ -7923,7 +7922,6 @@ packages: dependencies: '@vue/compiler-dom': registry.npmmirror.com/@vue/compiler-dom/3.2.26 '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.26 - dev: false registry.npmmirror.com/@vue/devtools-api/6.0.0-beta.21.1: resolution: @@ -7951,7 +7949,6 @@ packages: '@vue/shared': registry.npmmirror.com/@vue/shared/3.2.26 estree-walker: registry.npmmirror.com/estree-walker/2.0.2 magic-string: registry.nlark.com/magic-string/0.25.7 - dev: false registry.npmmirror.com/@vue/reactivity/3.2.26: resolution: @@ -9678,7 +9675,7 @@ packages: { integrity: sha1-MOvR73wv3/AcOk8VEESvJfqwUj4=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.npmmirror.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz?cache=0&sync_timestamp=1636378650851&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Feslint-visitor-keys%2Fdownload%2Feslint-visitor-keys-1.3.0.tgz + tarball: https://registry.npmmirror.com/eslint-visitor-keys/download/eslint-visitor-keys-1.3.0.tgz } name: eslint-visitor-keys version: 1.3.0 @@ -9690,7 +9687,7 @@ packages: { integrity: sha1-9lMoJZMFknOSyTjtROsKXJsr0wM=, registry: https://registry.npm.taobao.org/, - tarball: https://registry.npmmirror.com/eslint-visitor-keys/download/eslint-visitor-keys-2.1.0.tgz?cache=0&sync_timestamp=1636378650851&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Feslint-visitor-keys%2Fdownload%2Feslint-visitor-keys-2.1.0.tgz + tarball: https://registry.npmmirror.com/eslint-visitor-keys/download/eslint-visitor-keys-2.1.0.tgz } name: eslint-visitor-keys version: 2.1.0 @@ -11132,6 +11129,7 @@ packages: } name: path-to-regexp version: 6.2.0 + dev: true registry.npmmirror.com/picocolors/1.0.0: resolution: @@ -12350,6 +12348,24 @@ packages: - supports-color dev: true + registry.npmmirror.com/vite-plugin-vue-setup-extend/0.3.0_vite@2.7.10: + resolution: + { + integrity: sha512-9Nd7Bj4TftB2CoOAD2ZI4cHLW5zjKMF3LNihWbrnAPx3nuGBn33tM9SVUGBVjBB6uv1mGAPavwKCTU0xAD8qhw==, + registry: https://registry.npm.taobao.org/, + tarball: https://registry.npmmirror.com/vite-plugin-vue-setup-extend/download/vite-plugin-vue-setup-extend-0.3.0.tgz + } + id: registry.npmmirror.com/vite-plugin-vue-setup-extend/0.3.0 + name: vite-plugin-vue-setup-extend + version: 0.3.0 + peerDependencies: + vite: '>=2.0.0' + dependencies: + '@vue/compiler-sfc': registry.npmmirror.com/@vue/compiler-sfc/3.2.26 + magic-string: registry.nlark.com/magic-string/0.25.7 + vite: registry.npmmirror.com/vite/2.7.10_less@4.1.2 + dev: true + registry.npmmirror.com/vite-plugin-windicss/1.6.2_vite@2.7.10: resolution: { diff --git a/src/components/ContextMenu/index.ts b/src/components/ContextMenu/index.ts new file mode 100644 index 0000000..ad1cf4c --- /dev/null +++ b/src/components/ContextMenu/index.ts @@ -0,0 +1,3 @@ +import ContextMenu from './src/ContextMenu.vue' + +export { ContextMenu } diff --git a/src/components/ContextMenu/src/ContextMenu.vue b/src/components/ContextMenu/src/ContextMenu.vue new file mode 100644 index 0000000..7695c7b --- /dev/null +++ b/src/components/ContextMenu/src/ContextMenu.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/components/Menu/src/Menu.vue b/src/components/Menu/src/Menu.vue index 539eefb..98e1243 100644 --- a/src/components/Menu/src/Menu.vue +++ b/src/components/Menu/src/Menu.vue @@ -1,5 +1,5 @@ + + + diff --git a/src/components/TagsView/src/helper.ts b/src/components/TagsView/src/helper.ts new file mode 100644 index 0000000..22f6a50 --- /dev/null +++ b/src/components/TagsView/src/helper.ts @@ -0,0 +1,21 @@ +import type { RouteMeta, RouteLocationNormalizedLoaded } from 'vue-router' +import { pathResolve } from '@/utils/routerHelper' + +export const filterAffixTags = (routes: AppRouteRecordRaw[], parentPath = '') => { + let tags: RouteLocationNormalizedLoaded[] = [] + routes.forEach((route) => { + const meta = route.meta as RouteMeta + const tagPath = pathResolve(parentPath, route.path) + if (meta?.affix) { + tags.push({ ...route, path: tagPath, fullPath: tagPath } as RouteLocationNormalizedLoaded) + } + if (route.children) { + const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath) + if (tempTags.length >= 1) { + tags = [...tags, ...tempTags] + } + } + }) + + return tags +} diff --git a/src/layout/Layout.vue b/src/layout/Layout.vue index 23eb7da..57be87d 100644 --- a/src/layout/Layout.vue +++ b/src/layout/Layout.vue @@ -1,6 +1,5 @@ + + diff --git a/src/locales/en.ts b/src/locales/en.ts index 016a725..23a8508 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -11,7 +11,13 @@ export default { reminder: 'Reminder', loginOutMessage: 'Exit the system?', ok: 'OK', - cancel: 'Cancel' + cancel: 'Cancel', + reload: 'Reload current', + closeTab: 'Close current', + closeTheLeftTab: 'Close left', + closeTheRightTab: 'Close right', + closeOther: 'Close other', + closeAll: 'Close all' }, size: { default: 'Default', diff --git a/src/locales/zh-CN.ts b/src/locales/zh-CN.ts index f0e0d83..3843588 100644 --- a/src/locales/zh-CN.ts +++ b/src/locales/zh-CN.ts @@ -11,7 +11,13 @@ export default { reminder: '温馨提示', loginOutMessage: '是否退出本系统?', ok: '确定', - cancel: '取消' + cancel: '取消', + reload: '重新加载', + closeTab: '关闭标签页', + closeTheLeftTab: '关闭左侧标签页', + closeTheRightTab: '关闭右侧标签页', + closeOther: '关闭其他标签页', + closeAll: '关闭全部标签页' }, size: { default: '默认', diff --git a/src/router/index.ts b/src/router/index.ts index 9da8fb6..2b6be16 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -20,7 +20,8 @@ export const constantRouterMap: AppRouteRecordRaw[] = [ } ], meta: { - hidden: true + hidden: true, + noTagsView: true } }, { @@ -107,7 +108,8 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [ name: 'Icons', meta: { title: '图标', - icon: 'carbon:skill-level-advanced' + icon: 'carbon:skill-level-advanced', + affix: true } } ] diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts index 24bbcbb..66a779c 100644 --- a/src/store/modules/tagsView.ts +++ b/src/store/modules/tagsView.ts @@ -1,8 +1,9 @@ -// import router from '@/router' +import router from '@/router' import type { RouteLocationNormalizedLoaded } from 'vue-router' import { getRawRoute } from '@/utils/routerHelper' import { defineStore } from 'pinia' import { store } from '../index' +import { findIndex } from '@/utils' export interface TagsViewState { visitedViews: RouteLocationNormalizedLoaded[] @@ -24,18 +25,24 @@ export const useTagsViewStore = defineStore({ } }, actions: { - ADD_VISITED_VIEW(view: RouteLocationNormalizedLoaded): void { - if (this.visitedViews.some((v: RouteLocationNormalizedLoaded) => v.path === view.path)) return + // 新增缓存和tag + addView(view: RouteLocationNormalizedLoaded): void { + this.addVisitedView(view) + this.addCachedView() + }, + // 新增tag + addVisitedView(view: RouteLocationNormalizedLoaded) { + if (this.visitedViews.some((v) => v.path === view.path)) return if (view.meta?.noTagsView) return this.visitedViews.push( Object.assign({}, view, { - title: view.meta.title || 'no-name' + title: view.meta?.title || 'no-name' }) ) }, - SET_CACHED_VIEW(): void { + // 新增缓存 + addCachedView() { const cacheMap: Set = new Set() - for (const v of this.visitedViews) { const item = getRawRoute(v) const needCache = !item.meta?.noCache @@ -45,9 +52,17 @@ export const useTagsViewStore = defineStore({ const name = item.name as string cacheMap.add(name) } + if (Array.from(this.cachedViews).sort().toString() === Array.from(cacheMap).sort().toString()) + return this.cachedViews = cacheMap }, - DEL_VISITED_VIEW(view: RouteLocationNormalizedLoaded): void { + // 删除某个 + delView(view: RouteLocationNormalizedLoaded) { + this.delVisitedView(view) + this.addCachedView() + }, + // 删除tag + delVisitedView(view: RouteLocationNormalizedLoaded) { for (const [i, v] of this.visitedViews.entries()) { if (v.path === view.path) { this.visitedViews.splice(i, 1) @@ -55,117 +70,60 @@ export const useTagsViewStore = defineStore({ } } }, - DEL_CACHED_VIEW(): void { - // const route = router.currentRoute.value - // for (const [key, value] of this.cachedViews) { - // const index = value.findIndex((item: string) => item === (route.name as string)) - // if (index === -1) { - // continue - // } - // if (value.length === 1) { - // this.cachedViews.delete(key) - // continue - // } - // value.splice(index, 1) - // this.cachedViews.set(key, value) - // } + // 删除缓存 + delCachedView() { + const route = router.currentRoute.value + const index = findIndex(this.getCachedViews, (v) => v === route.name) + if (index > -1) { + this.cachedViews.delete(this.getCachedViews[index]) + } }, - DEL_OTHERS_VISITED_VIEWS(view: RouteLocationNormalizedLoaded): void { - this.visitedViews = this.visitedViews.filter((v) => { - return v.meta.affix || v.path === view.path - }) + // 删除所有缓存和tag + delAllViews() { + this.delAllVisitedViews() + this.addCachedView() }, - DEL_ALL_VISITED_VIEWS(): void { - // keep affix tags + // 删除所有tag + delAllVisitedViews() { const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) this.visitedViews = affixTags }, - UPDATE_VISITED_VIEW(view: RouteLocationNormalizedLoaded): void { - for (let v of this.visitedViews) { - if (v.path === view.path) { - v = Object.assign(v, view) - break - } - } - }, - addView(view: RouteLocationNormalizedLoaded): void { - this.addVisitedView(view) + // 删除其他 + delOthersViews(view: RouteLocationNormalizedLoaded) { + this.delOthersVisitedViews(view) this.addCachedView() }, - addVisitedView(view: RouteLocationNormalizedLoaded): void { - this.ADD_VISITED_VIEW(view) + // 删除其他tag + delOthersVisitedViews(view: RouteLocationNormalizedLoaded) { + this.visitedViews = this.visitedViews.filter((v) => { + return v?.meta?.affix || v.path === view.path + }) }, - addCachedView(): void { - this.SET_CACHED_VIEW() - }, - delView(view: RouteLocationNormalizedLoaded): Promise { - return new Promise((resolve) => { - this.delVisitedView(view) - this.SET_CACHED_VIEW() - resolve({ - visitedViews: [...this.visitedViews], - cachedViews: [...this.cachedViews] + // 删除左侧 + delLeftViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i > index }) - }) + this.addCachedView() + } }, - delVisitedView(view: RouteLocationNormalizedLoaded): Promise { - return new Promise((resolve) => { - this.DEL_VISITED_VIEW(view) - resolve([...this.visitedViews]) - }) - }, - delCachedView(): Promise { - return new Promise((resolve) => { - this.DEL_CACHED_VIEW() - resolve([...this.cachedViews]) - }) - }, - delOthersViews(view: RouteLocationNormalizedLoaded): Promise { - return new Promise((resolve) => { - this.delOthersVisitedViews(view) - this.SET_CACHED_VIEW() - resolve({ - visitedViews: [...this.visitedViews], - cachedViews: [...this.cachedViews] + // 删除右侧 + delRightViews(view: RouteLocationNormalizedLoaded) { + const index = findIndex( + this.visitedViews, + (v) => v.path === view.path + ) + if (index > -1) { + this.visitedViews = this.visitedViews.filter((v, i) => { + return v?.meta?.affix || v.path === view.path || i < index }) - }) - }, - delOthersVisitedViews(view: RouteLocationNormalizedLoaded): Promise { - return new Promise((resolve) => { - this.DEL_OTHERS_VISITED_VIEWS(view) - resolve([...this.visitedViews]) - }) - }, - delOthersCachedViews(): Promise { - return new Promise((resolve) => { - this.SET_CACHED_VIEW() - resolve([...this.cachedViews]) - }) - }, - delAllViews(): Promise { - return new Promise((resolve) => { - this.delAllVisitedViews() - this.SET_CACHED_VIEW() - resolve({ - visitedViews: [...this.visitedViews], - cachedViews: [...this.cachedViews] - }) - }) - }, - delAllVisitedViews(): Promise { - return new Promise((resolve) => { - this.DEL_ALL_VISITED_VIEWS() - resolve([...this.visitedViews]) - }) - }, - delAllCachedViews(): Promise { - return new Promise((resolve) => { - this.SET_CACHED_VIEW() - resolve([...this.cachedViews]) - }) - }, - updateVisitedView(view: RouteLocationNormalizedLoaded): void { - this.UPDATE_VISITED_VIEW(view) + this.addCachedView() + } } } }) diff --git a/src/utils/domUtils.ts b/src/utils/domUtils.ts new file mode 100644 index 0000000..dbc1989 --- /dev/null +++ b/src/utils/domUtils.ts @@ -0,0 +1,289 @@ +import { isServer } from './is' +const ieVersion = isServer ? 0 : Number((document as any).documentMode) +const SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g +const MOZ_HACK_REGEXP = /^moz([A-Z])/ + +export interface ViewportOffsetResult { + left: number + top: number + right: number + bottom: number + rightIncludeBody: number + bottomIncludeBody: number +} + +/* istanbul ignore next */ +const trim = function (string: string) { + return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '') +} + +/* istanbul ignore next */ +const camelCase = function (name: string) { + return name + .replace(SPECIAL_CHARS_REGEXP, function (_, __, letter, offset) { + return offset ? letter.toUpperCase() : letter + }) + .replace(MOZ_HACK_REGEXP, 'Moz$1') +} + +/* istanbul ignore next */ +export function hasClass(el: Element, cls: string) { + if (!el || !cls) return false + if (cls.indexOf(' ') !== -1) { + throw new Error('className should not contain space.') + } + if (el.classList) { + return el.classList.contains(cls) + } else { + return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1 + } +} + +/* istanbul ignore next */ +export function addClass(el: Element, cls: string) { + if (!el) return + let curClass = el.className + const classes = (cls || '').split(' ') + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.add(clsName) + } else if (!hasClass(el, clsName)) { + curClass += ' ' + clsName + } + } + if (!el.classList) { + el.className = curClass + } +} + +/* istanbul ignore next */ +export function removeClass(el: Element, cls: string) { + if (!el || !cls) return + const classes = cls.split(' ') + let curClass = ' ' + el.className + ' ' + + for (let i = 0, j = classes.length; i < j; i++) { + const clsName = classes[i] + if (!clsName) continue + + if (el.classList) { + el.classList.remove(clsName) + } else if (hasClass(el, clsName)) { + curClass = curClass.replace(' ' + clsName + ' ', ' ') + } + } + if (!el.classList) { + el.className = trim(curClass) + } +} + +export function getBoundingClientRect(element: Element): DOMRect | number { + if (!element || !element.getBoundingClientRect) { + return 0 + } + return element.getBoundingClientRect() +} + +/** + * 获取当前元素的left、top偏移 + * left:元素最左侧距离文档左侧的距离 + * top:元素最顶端距离文档顶端的距离 + * right:元素最右侧距离文档右侧的距离 + * bottom:元素最底端距离文档底端的距离 + * rightIncludeBody:元素最左侧距离文档右侧的距离 + * bottomIncludeBody:元素最底端距离文档最底部的距离 + * + * @description: + */ +export function getViewportOffset(element: Element): ViewportOffsetResult { + const doc = document.documentElement + + const docScrollLeft = doc.scrollLeft + const docScrollTop = doc.scrollTop + const docClientLeft = doc.clientLeft + const docClientTop = doc.clientTop + + const pageXOffset = window.pageXOffset + const pageYOffset = window.pageYOffset + + const box = getBoundingClientRect(element) + + const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box as DOMRect + + const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0) + const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0) + const offsetLeft = retLeft + pageXOffset + const offsetTop = rectTop + pageYOffset + + const left = offsetLeft - scrollLeft + const top = offsetTop - scrollTop + + const clientWidth = window.document.documentElement.clientWidth + const clientHeight = window.document.documentElement.clientHeight + return { + left: left, + top: top, + right: clientWidth - rectWidth - left, + bottom: clientHeight - rectHeight - top, + rightIncludeBody: clientWidth - left, + bottomIncludeBody: clientHeight - top + } +} + +/* istanbul ignore next */ +export const on = function ( + element: HTMLElement | Document | Window, + event: string, + handler: EventListenerOrEventListenerObject +): void { + if (element && event && handler) { + element.addEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const off = function ( + element: HTMLElement | Document | Window, + event: string, + handler: any +): void { + if (element && event && handler) { + element.removeEventListener(event, handler, false) + } +} + +/* istanbul ignore next */ +export const once = function (el: HTMLElement, event: string, fn: EventListener): void { + const listener = function (this: any, ...args: unknown[]) { + if (fn) { + // @ts-ignore + fn.apply(this, args) + } + off(el, event, listener) + } + on(el, event, listener) +} + +/* istanbul ignore next */ +export const getStyle = + ieVersion < 9 + ? function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'styleFloat' + } + try { + switch (styleName) { + case 'opacity': + try { + return element.filters.item('alpha').opacity / 100 + } catch (e) { + return 1.0 + } + default: + return element.style[styleName] || element.currentStyle + ? element.currentStyle[styleName] + : null + } + } catch (e) { + return element.style[styleName] + } + } + : function (element: Element | any, styleName: string) { + if (isServer) return + if (!element || !styleName) return null + styleName = camelCase(styleName) + if (styleName === 'float') { + styleName = 'cssFloat' + } + try { + const computed = (document as any).defaultView.getComputedStyle(element, '') + return element.style[styleName] || computed ? computed[styleName] : null + } catch (e) { + return element.style[styleName] + } + } + +/* istanbul ignore next */ +export function setStyle(element: Element | any, styleName: any, value: any) { + if (!element || !styleName) return + + if (typeof styleName === 'object') { + for (const prop in styleName) { + if (Object.prototype.hasOwnProperty.call(styleName, prop)) { + setStyle(element, prop, styleName[prop]) + } + } + } else { + styleName = camelCase(styleName) + if (styleName === 'opacity' && ieVersion < 9) { + element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')' + } else { + element.style[styleName] = value + } + } +} + +/* istanbul ignore next */ +export const isScroll = (el: Element, vertical: any) => { + if (isServer) return + + const determinedDirection = vertical !== null || vertical !== undefined + const overflow = determinedDirection + ? vertical + ? getStyle(el, 'overflow-y') + : getStyle(el, 'overflow-x') + : getStyle(el, 'overflow') + + return overflow.match(/(scroll|auto)/) +} + +/* istanbul ignore next */ +export const getScrollContainer = (el: Element, vertical?: any) => { + if (isServer) return + + let parent: any = el + while (parent) { + if ([window, document, document.documentElement].includes(parent)) { + return window + } + if (isScroll(parent, vertical)) { + return parent + } + parent = parent.parentNode + } + + return parent +} + +/* istanbul ignore next */ +export const isInContainer = (el: Element, container: any) => { + if (isServer || !el || !container) return false + + const elRect = el.getBoundingClientRect() + let containerRect + + if ([window, document, document.documentElement, null, undefined].includes(container)) { + containerRect = { + top: 0, + right: window.innerWidth, + bottom: window.innerHeight, + left: 0 + } + } else { + containerRect = container.getBoundingClientRect() + } + + return ( + elRect.top < containerRect.bottom && + elRect.bottom > containerRect.top && + elRect.right > containerRect.left && + elRect.left < containerRect.right + ) +} diff --git a/src/utils/index.ts b/src/utils/index.ts index a6049bf..aa3c0eb 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -38,3 +38,24 @@ export const underlineToHump = (str: string): string => { export const setCssVar = (prop: string, val: any, dom = document.documentElement) => { dom.style.setProperty(prop, val) } + +/** + * 查找数组对象的某个下标 + * @param {Array} ary 查找的数组 + * @param {Functon} fn 判断的方法 + */ +// eslint-disable-next-line +export const findIndex = (ary: Array, fn: Fn): number => { + if (ary.findIndex) { + return ary.findIndex(fn) + } + let index = -1 + ary.some((item: T, i: number, ary: Array) => { + const ret: T = fn(item, i, ary) + if (ret) { + index = i + return ret + } + }) + return index +} diff --git a/src/views/Level/Menu111.vue b/src/views/Level/Menu111.vue index 6624131..88e5fc5 100644 --- a/src/views/Level/Menu111.vue +++ b/src/views/Level/Menu111.vue @@ -1,5 +1,10 @@ - + diff --git a/src/views/Login/Login.vue b/src/views/Login/Login.vue index 36dd896..3dec409 100644 --- a/src/views/Login/Login.vue +++ b/src/views/Login/Login.vue @@ -2,7 +2,6 @@ import { LoginForm } from './components' import { ThemeSwitch } from '@/components/ThemeSwitch' import { LocaleDropdown } from '@/components/LocaleDropdown' -import { useDesign } from '@/hooks/web/useDesign' import { useI18n } from '@/hooks/web/useI18n' import { underlineToHump } from '@/utils' import { useAppStore } from '@/store/modules/app' @@ -10,22 +9,14 @@ import { useAppStore } from '@/store/modules/app' const appStore = useAppStore() const { t } = useI18n() - -const { getPrefixCls } = useDesign() - -const prefixCls = getPrefixCls('login')