Browse Source

wip: use unocss

xingyu 1 year ago
parent
commit
4249465b7c

+ 2 - 2
build/vite/index.ts

@@ -1,7 +1,6 @@
 import { resolve } from 'path'
 import Vue from '@vitejs/plugin-vue'
 import VueJsx from '@vitejs/plugin-vue-jsx'
-import WindiCSS from 'vite-plugin-windicss'
 import progress from 'vite-plugin-progress'
 import EslintPlugin from 'vite-plugin-eslint'
 import PurgeIcons from 'vite-plugin-purge-icons'
@@ -15,6 +14,7 @@ import viteCompression from 'vite-plugin-compression'
 import topLevelAwait from 'vite-plugin-top-level-await'
 import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
 import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+import UnoCSS from 'unocss/vite'
 
 export function createVitePlugins() {
   const root = process.cwd()
@@ -27,7 +27,7 @@ export function createVitePlugins() {
   return [
     Vue(),
     VueJsx(),
-    WindiCSS(),
+    UnoCSS(),
     progress(),
     PurgeIcons(),
     ElementPlus({}),

+ 4 - 3
package.json

@@ -87,9 +87,11 @@
     "@types/qs": "^6.9.7",
     "@typescript-eslint/eslint-plugin": "^6.2.0",
     "@typescript-eslint/parser": "^6.2.0",
+    "@unocss/transformer-variant-group": "^0.51.4",
     "@vitejs/plugin-legacy": "^4.1.1",
     "@vitejs/plugin-vue": "^4.2.3",
     "@vitejs/plugin-vue-jsx": "^3.0.1",
+    "@vue-macros/volar": "^0.12.3",
     "autoprefixer": "^10.4.14",
     "bpmn-js": "^8.9.0",
     "bpmn-js-properties-panel": "^0.46.0",
@@ -114,6 +116,7 @@
     "stylelint-order": "^6.0.3",
     "terser": "^5.19.2",
     "typescript": "5.1.6",
+    "unocss": "^0.54.0",
     "unplugin-auto-import": "^0.16.6",
     "unplugin-element-plus": "^0.7.2",
     "unplugin-vue-components": "^0.25.1",
@@ -125,9 +128,7 @@
     "vite-plugin-purge-icons": "^0.9.2",
     "vite-plugin-svg-icons": "^2.0.1",
     "vite-plugin-top-level-await": "^1.3.1",
-    "vite-plugin-windicss": "^1.9.0",
-    "vue-tsc": "^1.8.8",
-    "windicss": "^3.5.6"
+    "vue-tsc": "^1.8.8"
   },
   "license": "MIT",
   "repository": {

+ 1 - 1
src/components/ContentDetailWrap/src/ContentDetailWrap.vue

@@ -28,7 +28,7 @@ onMounted(() => {
       <div
         :class="[
           `${prefixCls}-header`,
-          'flex border-bottom-1 h-50px items-center text-center pr-10px'
+          'lex b-b-1 h-50px items-center text-center bg-white pr-10px'
         ]"
       >
         <div :class="[`${prefixCls}-header__back`, 'flex pl-10px pr-10px ']">

+ 2 - 2
src/components/Descriptions/src/Descriptions.vue

@@ -71,14 +71,14 @@ const toggleClick = () => {
   <div
     :class="[
       prefixCls,
-      'bg-[var(--el-color-white)] dark:(bg-[var(--el-bg-color)] border-[var(--el-border-color)] border-1px)'
+      'bg-[var(--el-color-white)] dark:bg-[var(--el-bg-color)] dark:border-[var(--el-border-color)] dark:border-1px'
     ]"
   >
     <div
       v-if="title"
       :class="[
         `${prefixCls}-header`,
-        'h-50px flex justify-between items-center border-bottom-1 border-solid border-[var(--tags-view-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
+        'h-50px flex justify-between items-center b-b-1 border-solid border-[var(--el-border-color)] px-10px cursor-pointer dark:border-[var(--el-border-color)]'
       ]"
       @click="toggleClick"
     >

+ 12 - 16
src/components/Dialog/src/Dialog.vue

@@ -99,13 +99,19 @@ const dialogStyle = computed(() => {
 </template>
 
 <style lang="scss">
-.#{$elNamespace}-dialog__header {
-  margin-right: 0 !important;
-  border-bottom: 1px solid var(--tags-view-border-color);
-}
+.#{$elNamespace}-dialog {
+  &__header {
+    margin-right: 0 !important;
+    border-bottom: 1px solid var(--el-border-color);
+  }
 
-.#{$elNamespace}-dialog__footer {
-  border-top: 1px solid var(--tags-view-border-color);
+  &__body {
+    padding: 0 !important;
+  }
+
+  &__footer {
+    border-top: 1px solid var(--el-border-color);
+  }
 }
 
 .is-hover {
@@ -113,14 +119,4 @@ const dialogStyle = computed(() => {
     color: var(--el-color-primary) !important;
   }
 }
-
-.dark {
-  .#{$elNamespace}-dialog__header {
-    border-bottom: 1px solid var(--el-border-color);
-  }
-
-  .#{$elNamespace}-dialog__footer {
-    border-top: 1px solid var(--el-border-color);
-  }
-}
 </style>

+ 2 - 3
src/components/Editor/src/Editor.vue

@@ -164,7 +164,6 @@ const handleChange = (editor: IDomEditor) => {
 // 组件销毁时,及时销毁编辑器
 onBeforeUnmount(() => {
   const editor = unref(editorRef.value)
-  if (editor === null) return
 
   // 销毁,并移除 editor
   editor?.destroy()
@@ -181,12 +180,12 @@ defineExpose({
 </script>
 
 <template>
-  <div class="border-1 border-solid border-[var(--tags-view-border-color)] z-99">
+  <div class="border-1 border-solid border-[var(--el-border-color)] z-99">
     <!-- 工具栏 -->
     <Toolbar
       :editor="editorRef"
       :editorId="editorId"
-      class="border-bottom-1 border-solid border-[var(--tags-view-border-color)]"
+      class="border-0 b-b-1 border-solid border-[var(--el-border-color)]"
     />
     <!-- 编辑器 -->
     <Editor

+ 17 - 10
src/layout/components/AppView.vue

@@ -18,26 +18,33 @@ const tagsViewStore = useTagsViewStore()
 const getCaches = computed((): string[] => {
   return tagsViewStore.getCachedViews
 })
+
+const tagsView = computed(() => appStore.getTagsView)
 </script>
 
 <template>
   <section
     :class="[
-      'p-[var(--app-content-padding)] w-[100%] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]',
+      'p-[var(--app-content-padding)] w-[calc(100%-var(--app-content-padding)-var(--app-content-padding))] bg-[var(--app-content-bg-color)] dark:bg-[var(--el-bg-color)]',
       {
-        '!min-h-[calc(100%-var(--app-footer-height))]':
-          ((fixedHeader && (layout === 'classic' || layout === 'topLeft')) || layout === 'top') &&
-          footer,
-
-        '!min-h-[calc(100%-var(--tags-view-height)-var(--top-tool-height)-var(--app-footer-height))]':
+        '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]':
+          (fixedHeader &&
+            (layout === 'classic' || layout === 'topLeft' || layout === 'top') &&
+            footer) ||
+          (!tagsView && layout === 'top' && footer),
+        '!min-h-[calc(100%-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height)-var(--tags-view-height))]':
+          tagsView && layout === 'top' && footer,
+
+        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--top-tool-height)-var(--app-footer-height))]':
           !fixedHeader && layout === 'classic' && footer,
 
-        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]':
-          !fixedHeader && (layout === 'topLeft' || layout === 'top') && footer,
+        '!min-h-[calc(100%-var(--tags-view-height)-var(--app-content-padding)-var(--app-content-padding)-var(--app-footer-height))]':
+          !fixedHeader && layout === 'topLeft' && footer,
 
-        '!min-h-[calc(100%-var(--top-tool-height))]': fixedHeader && layout === 'cutMenu' && footer,
+        '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding))]':
+          fixedHeader && layout === 'cutMenu' && footer,
 
-        '!min-h-[calc(100%-var(--top-tool-height)-var(--tags-view-height))]':
+        '!min-h-[calc(100%-var(--top-tool-height)-var(--app-content-padding)-var(--app-content-padding)-var(--tags-view-height))]':
           !fixedHeader && layout === 'cutMenu' && footer
       }
     ]"

+ 1 - 1
src/layout/components/LocaleDropdown/src/LocaleDropdown.vue

@@ -38,7 +38,7 @@ const setLang = (lang: LocaleType) => {
       :class="$attrs.class"
       :color="color"
       :size="18"
-      class="cursor-pointer"
+      class="cursor-pointer !p-0"
       icon="ion:language-sharp"
     />
     <template #dropdown>

+ 1 - 2
src/layout/components/Logo/src/Logo.vue

@@ -62,8 +62,7 @@ watch(
       :class="[
         prefixCls,
         layout !== 'classic' ? `${prefixCls}__Top` : '',
-        'flex !h-[var(--logo-height)] items-center cursor-pointer justify-center relative',
-        'dark:bg-[var(--el-bg-color)]'
+        'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative decoration-none overflow-hidden'
       ]"
       to="/"
     >

+ 0 - 9
src/layout/components/Menu/src/Menu.vue

@@ -138,15 +138,6 @@ $prefix-cls: #{$namespace}-menu;
   position: relative;
   transition: width var(--transition-time-02);
 
-  &:after {
-    position: absolute;
-    top: 0;
-    right: 0;
-    height: 100%;
-    border-left: 1px solid var(--left-menu-border-color);
-    content: '';
-  }
-
   :deep(.#{$elNamespace}-menu) {
     width: 100% !important;
     border-right: none;

+ 0 - 1
src/layout/components/Setting/src/Setting.vue

@@ -44,7 +44,6 @@ const setHeaderTheme = (color: string) => {
   setCssVar('--top-header-bg-color', color)
   setCssVar('--top-header-text-color', textColor)
   setCssVar('--top-header-hover-color', textHoverColor)
-  setCssVar('--top-tool-border-color', topToolBorderColor)
   appStore.setTheme({
     topHeaderBgColor: color,
     topHeaderTextColor: textColor,

+ 2 - 13
src/layout/components/TabMenu/src/TabMenu.vue

@@ -139,7 +139,7 @@ export default defineComponent({
         id={`${variables.namespace}-menu`}
         class={[
           prefixCls,
-          'relative bg-[var(--left-menu-bg-color)] top-1px z-3000',
+          'relative bg-[var(--left-menu-bg-color)] top-1px z-3000 layout-border__right',
           {
             'w-[var(--tab-menu-max-width)]': !unref(collapse),
             'w-[var(--tab-menu-min-width)]': unref(collapse)
@@ -195,7 +195,7 @@ export default defineComponent({
         </div>
         <Menu
           class={[
-            '!absolute top-0 border-left-1 border-solid border-[var(--left-menu-bg-light-color)]',
+            '!absolute top-0',
             {
               '!left-[var(--tab-menu-min-width)]': unref(collapse),
               '!left-[var(--tab-menu-max-width)]': !unref(collapse),
@@ -217,16 +217,6 @@ $prefix-cls: #{$namespace}-tab-menu;
 .#{$prefix-cls} {
   transition: all var(--transition-time-02);
 
-  &::after {
-    position: absolute;
-    top: 0;
-    right: 0;
-    width: 1px;
-    height: 100%;
-    border-left: 1px solid var(--left-menu-border-color);
-    content: '';
-  }
-
   &__item {
     color: var(--left-menu-text-color);
     transition: all var(--transition-time-02);
@@ -240,7 +230,6 @@ $prefix-cls: #{$namespace}-tab-menu;
   &--collapse {
     color: var(--left-menu-text-color);
     background-color: var(--left-menu-bg-light-color);
-    border-top: 1px solid var(--left-menu-border-color);
   }
 
   .is-active {

+ 57 - 61
src/layout/components/TagsView/src/TagsView.vue

@@ -1,17 +1,17 @@
 <script lang="ts" setup>
+import { onMounted, watch, computed, unref, ref, nextTick } from 'vue'
+import { useRouter } from 'vue-router'
 import type { RouteLocationNormalizedLoaded, RouterLinkProps } from 'vue-router'
 import { usePermissionStore } from '@/store/modules/permission'
 import { useTagsViewStore } from '@/store/modules/tagsView'
 import { useAppStore } from '@/store/modules/app'
-
+import { useI18n } from '@/hooks/web/useI18n'
 import { filterAffixTags } from './helper'
 import { ContextMenu, ContextMenuExpose } from '@/layout/components/ContextMenu'
 import { useDesign } from '@/hooks/web/useDesign'
+import { useTemplateRefsList } from '@vueuse/core'
 import { ElScrollbar } from 'element-plus'
 import { useScrollTo } from '@/hooks/event/useScrollTo'
-import { useTemplateRefsList } from '@vueuse/core'
-
-defineOptions({ name: 'TagsView' })
 
 const { getPrefixCls } = useDesign()
 
@@ -35,6 +35,8 @@ const appStore = useAppStore()
 
 const tagsViewIcon = computed(() => appStore.getTagsViewIcon)
 
+const isDark = computed(() => appStore.getIsDark)
+
 // 初始化tag
 const initTags = () => {
   affixTagArr.value = filterAffixTags(unref(routers))
@@ -73,7 +75,7 @@ const closeAllTags = () => {
   toLastView()
 }
 
-// 关闭其
+// 关闭其
 const closeOthersTags = () => {
   tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded)
 }
@@ -128,6 +130,7 @@ const moveToCurrentTag = async () => {
       if (v.fullPath !== unref(currentRoute).fullPath) {
         tagsViewStore.updateVisitedView(unref(currentRoute))
       }
+
       break
     }
   }
@@ -263,29 +266,21 @@ watch(
     class="flex w-full relative bg-[#fff] dark:bg-[var(--el-bg-color)]"
   >
     <span
-      :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] cursor-pointer"
+      :class="`${prefixCls}__tool ${prefixCls}__tool--first`"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="move(-200)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:d-arrow-left"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <div class="overflow-hidden flex-1">
       <ElScrollbar ref="scrollbarRef" class="h-full" @scroll="scroll">
         <div class="flex h-full">
           <ContextMenu
-            v-for="item in visitedViews"
-            :key="item.fullPath"
             :ref="itemRefs.set"
-            :class="[
-              `${prefixCls}__item`,
-              item?.meta?.affix ? `${prefixCls}__item--affix` : '',
-              {
-                'is-active': isActive(item)
-              }
-            ]"
             :schema="[
               {
                 icon: 'ep:refresh',
@@ -343,14 +338,23 @@ watch(
                 }
               }
             ]"
+            v-for="item in visitedViews"
+            :key="item.fullPath"
             :tag-item="item"
+            :class="[
+              `${prefixCls}__item`,
+              item?.meta?.affix ? `${prefixCls}__item--affix` : '',
+              {
+                'is-active': isActive(item)
+              }
+            ]"
             @visible-change="visibleChange"
           >
             <div>
-              <router-link :ref="tagLinksRefs.set" v-slot="{ navigate }" :to="{ ...item }" custom>
+              <router-link :ref="tagLinksRefs.set" :to="{ ...item }" custom v-slot="{ navigate }">
                 <div
-                  class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
                   @click="navigate"
+                  class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
                 >
                   <Icon
                     v-if="
@@ -366,9 +370,9 @@ watch(
                   {{ t(item?.meta?.title as string) }}
                   <Icon
                     :class="`${prefixCls}__item--close`"
-                    :size="12"
                     color="#333"
                     icon="ep:close"
+                    :size="12"
                     @click.prevent.stop="closeSelectedTag(item)"
                   />
                 </div>
@@ -380,25 +384,28 @@ watch(
     </div>
     <span
       :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="move(200)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:d-arrow-right"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <span
       :class="`${prefixCls}__tool`"
-      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer"
+      class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
       @click="refreshSelectedTag(selectedTag)"
     >
       <Icon
-        :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
         icon="ep:refresh-right"
+        color="var(--el-text-color-placeholder)"
+        :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
       />
     </span>
     <ContextMenu
+      trigger="click"
       :schema="[
         {
           icon: 'ep:refresh',
@@ -450,15 +457,15 @@ watch(
           }
         }
       ]"
-      trigger="click"
     >
       <span
         :class="`${prefixCls}__tool`"
-        class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] text-center leading-[var(--tags-view-height)] cursor-pointer block"
+        class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer block"
       >
         <Icon
-          :color="appStore.getIsDark ? 'var(--el-text-color-regular)' : '#333'"
           icon="ep:menu"
+          color="var(--el-text-color-placeholder)"
+          :hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
         />
       </span>
     </ContextMenu>
@@ -475,47 +482,49 @@ $prefix-cls: #{$namespace}-tags-view;
 
   &__tool {
     position: relative;
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
-
-    &:hover {
-      :deep(span) {
-        color: var(--el-color-black) !important;
-      }
-    }
 
-    &::after {
+    &::before {
       position: absolute;
       top: 1px;
       left: 0;
       width: 100%;
       height: calc(100% - 1px);
-      border-right: 1px solid var(--tags-view-border-color);
-      border-left: 1px solid var(--tags-view-border-color);
+      border-left: 1px solid var(--el-border-color);
       content: '';
     }
+
+    &--first {
+      &::before {
+        position: absolute;
+        top: 1px;
+        left: 0;
+        width: 100%;
+        height: calc(100% - 1px);
+        border-right: 1px solid var(--el-border-color);
+        border-left: none;
+        content: '';
+      }
+    }
   }
 
   &__item {
     position: relative;
     top: 2px;
-    height: calc(100% - 4px);
-    padding-right: 16px;
+    height: calc(100% - 6px);
+    padding-right: 25px;
     margin-left: 4px;
     font-size: 12px;
-    border-radius: 3px;
     cursor: pointer;
     border: 1px solid #d9d9d9;
+    border-radius: 2px;
 
     &--close {
       position: absolute;
       top: 50%;
-      right: 3px;
+      right: 5px;
       display: none;
       transform: translate(0, -50%);
     }
-
     &:not(.#{$prefix-cls}__item--affix):hover {
       .#{$prefix-cls}__item--close {
         display: block;
@@ -533,7 +542,6 @@ $prefix-cls: #{$namespace}-tags-view;
     color: var(--el-color-white);
     background-color: var(--el-color-primary);
     border: 1px solid var(--el-color-primary);
-
     .#{$prefix-cls}__item--close {
       :deep(span) {
         color: var(--el-color-white) !important;
@@ -545,26 +553,14 @@ $prefix-cls: #{$namespace}-tags-view;
 .dark {
   .#{$prefix-cls} {
     &__tool {
-      &:hover {
-        :deep(span) {
-          color: #fff !important;
+      &--first {
+        &::after {
+          display: none;
         }
       }
-
-      &::after {
-        border-right: 1px solid var(--el-border-color);
-        border-left: 1px solid var(--el-border-color);
-      }
     }
 
     &__item {
-      position: relative;
-      top: 2px;
-      height: calc(100% - 4px);
-      padding-right: 16px;
-      font-size: 12px;
-      border-radius: 3px;
-      cursor: pointer;
       border: 1px solid var(--el-border-color);
     }
 
@@ -577,7 +573,7 @@ $prefix-cls: #{$namespace}-tags-view;
     &__item.is-active {
       color: var(--el-color-white);
       background-color: var(--el-color-primary);
-
+      border: 1px solid var(--el-color-primary);
       .#{$prefix-cls}__item--close {
         :deep(span) {
           color: var(--el-color-white) !important;

+ 7 - 7
src/layout/components/ToolHeader.vue

@@ -52,28 +52,28 @@ export default defineComponent({
         {layout.value !== 'top' ? (
           <div class="h-full flex items-center">
             {hamburger.value && layout.value !== 'cutMenu' ? (
-              <Collapse class="hover-trigger" color="var(--top-header-text-color)"></Collapse>
+              <Collapse class="custom-hover" color="var(--top-header-text-color)"></Collapse>
             ) : undefined}
-            {breadcrumb.value ? <Breadcrumb class="<md:hidden"></Breadcrumb> : undefined}
+            {breadcrumb.value ? <Breadcrumb class="lt-md:hidden"></Breadcrumb> : undefined}
           </div>
         ) : undefined}
         <div class="h-full flex items-center">
           {screenfull.value ? (
-            <Screenfull class="hover-trigger" color="var(--top-header-text-color)"></Screenfull>
+            <Screenfull class="custom-hover" color="var(--top-header-text-color)"></Screenfull>
           ) : undefined}
           {size.value ? (
-            <SizeDropdown class="hover-trigger" color="var(--top-header-text-color)"></SizeDropdown>
+            <SizeDropdown class="custom-hover" color="var(--top-header-text-color)"></SizeDropdown>
           ) : undefined}
           {locale.value ? (
             <LocaleDropdown
-              class="hover-trigger"
+              class="custom-hover"
               color="var(--top-header-text-color)"
             ></LocaleDropdown>
           ) : undefined}
           {message.value ? (
-            <Message class="hover-trigger" color="var(--top-header-text-color)"></Message>
+            <Message class="custom-hover" color="var(--top-header-text-color)"></Message>
           ) : undefined}
-          <UserInfo class="hover-trigger"></UserInfo>
+          <UserInfo></UserInfo>
         </div>
       </div>
     )

+ 1 - 1
src/layout/components/UserInfo/src/UserInfo.vue

@@ -51,7 +51,7 @@ const toDocument = () => {
 </script>
 
 <template>
-  <ElDropdown :class="prefixCls" trigger="click">
+  <ElDropdown class="custom-hover" :class="prefixCls" trigger="click">
     <div class="flex items-center">
       <img :src="avatar" alt="" class="w-[calc(var(--logo-height)-25px)] rounded-[50%]" />
       <span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">

+ 54 - 26
src/layout/components/useRenderLayout.tsx

@@ -39,11 +39,16 @@ export const useRenderLayout = () => {
   const renderClassic = () => {
     return (
       <>
-        <div class={['absolute top-0 left-0 h-full', { '!fixed z-3000': mobile.value }]}>
+        <div
+          class={[
+            'absolute top-0 left-0 h-full layout-border__right',
+            { '!fixed z-3000': mobile.value }
+          ]}
+        >
           {logo.value ? (
             <Logo
               class={[
-                'bg-[var(--left-menu-bg-color)] border-bottom-1 border-solid border-[var(--logo-border-color)] dark:border-[var(--el-border-color)]',
+                'bg-[var(--left-menu-bg-color)] relative',
                 {
                   '!pl-0': mobile.value && collapse.value,
                   'w-[var(--left-menu-min-width)]': appStore.getCollapse,
@@ -83,19 +88,26 @@ export const useRenderLayout = () => {
               class={[
                 {
                   'fixed top-0 left-0 z-10': fixedHeader.value,
-                  'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)]':
+                  'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)]':
                     collapse.value && fixedHeader.value && !mobile.value,
-                  'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)]':
+                  'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)]':
                     !collapse.value && fixedHeader.value && !mobile.value,
                   '!w-full !left-0': mobile.value
                 }
               ]}
               style="transition: all var(--transition-time-02);"
             >
-              <ToolHeader class="border-bottom-1 border-solid border-[var(--top-tool-border-color)] bg-[var(--top-header-bg-color)] dark:border-[var(--el-border-color)]"></ToolHeader>
+              <ToolHeader
+                class={[
+                  'bg-[var(--top-header-bg-color)]',
+                  {
+                    'layout-border__bottom': !tagsView.value
+                  }
+                ]}
+              ></ToolHeader>
 
               {tagsView.value ? (
-                <TagsView class="border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]"></TagsView>
+                <TagsView class="layout-border__bottom layout-border__top"></TagsView>
               ) : undefined}
             </div>
 
@@ -109,13 +121,13 @@ export const useRenderLayout = () => {
   const renderTopLeft = () => {
     return (
       <>
-        <div class="flex items-center bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger !pr-15px"></Logo> : undefined}
+        <div class="flex items-center bg-[var(--top-header-bg-color)] relative layout-border__bottom dark:bg-[var(--el-bg-color)]">
+          {logo.value ? <Logo class="custom-hover"></Logo> : undefined}
 
           <ToolHeader class="flex-1"></ToolHeader>
         </div>
         <div class="absolute top-[var(--logo-height)+1px] left-0 w-full h-[calc(100%-1px-var(--logo-height))] flex">
-          <Menu class="!h-full"></Menu>
+          <Menu class="!h-full relative layout-border__right"></Menu>
           <div
             class={[
               `${prefixCls}-content`,
@@ -142,12 +154,12 @@ export const useRenderLayout = () => {
               {tagsView.value ? (
                 <TagsView
                   class={[
-                    'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                    'layout-border__bottom absolute',
                     {
                       '!fixed top-0 left-0 z-10': fixedHeader.value,
-                      'w-[calc(100%-var(--left-menu-min-width))] left-[var(--left-menu-min-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--left-menu-min-width))] !left-[var(--left-menu-min-width)] mt-[calc(var(--logo-height)+1px)]':
                         collapse.value && fixedHeader.value,
-                      'w-[calc(100%-var(--left-menu-max-width))] left-[var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--left-menu-max-width))] !left-[var(--left-menu-max-width)] mt-[calc(var(--logo-height)+1px)]':
                         !collapse.value && fixedHeader.value
                     }
                   ]}
@@ -166,12 +178,28 @@ export const useRenderLayout = () => {
   const renderTop = () => {
     return (
       <>
-        <div class="flex items-center justify-between bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger"></Logo> : undefined}
+        <div
+          class={[
+            'flex items-center justify-between bg-[var(--top-header-bg-color)] relative',
+            {
+              'layout-border__bottom': !tagsView.value
+            }
+          ]}
+        >
+          {logo.value ? <Logo class="custom-hover"></Logo> : undefined}
           <Menu class="flex-1 px-10px h-[var(--top-tool-height)]"></Menu>
           <ToolHeader></ToolHeader>
         </div>
-        <div class={[`${prefixCls}-content`, 'h-full w-full']}>
+        <div
+          class={[
+            `${prefixCls}-content`,
+            'w-full',
+            {
+              'h-[calc(100%-var(--app-footer-height))]': !fixedHeader.value,
+              'h-[calc(100%-var(--tags-view-height)-var(--app-footer-height))]': fixedHeader.value
+            }
+          ]}
+        >
           <ElScrollbar
             v-loading={pageLoading.value}
             class={[
@@ -186,9 +214,9 @@ export const useRenderLayout = () => {
             {tagsView.value ? (
               <TagsView
                 class={[
-                  'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                  'layout-border__bottom layout-border__top relative',
                   {
-                    '!fixed w-full top-[var(--top-tool-height)] left-0': fixedHeader.value
+                    '!fixed w-full top-[calc(var(--top-tool-height)+1px)] left-0': fixedHeader.value
                   }
                 ]}
                 style="transition: width var(--transition-time-02), left var(--transition-time-02);"
@@ -205,12 +233,12 @@ export const useRenderLayout = () => {
   const renderCutMenu = () => {
     return (
       <>
-        <div class="flex items-center bg-[var(--top-header-bg-color)] border-bottom-1 border-solid border-[var(--top-tool-border-color)] dark:border-[var(--el-border-color)]">
-          {logo.value ? <Logo class="hover-trigger !pr-15px"></Logo> : undefined}
+        <div class="flex items-center bg-[var(--top-header-bg-color)] relative layout-border__bottom">
+          {logo.value ? <Logo class="custom-hover !pr-15px"></Logo> : undefined}
 
           <ToolHeader class="flex-1"></ToolHeader>
         </div>
-        <div class="absolute top-[var(--logo-height)] left-0 w-full h-[calc(100%-var(--logo-height))] flex">
+        <div class="absolute top-[var(--logo-height)] left-0 w-[calc(100%-2px)] h-[calc(100%-var(--logo-height))] flex">
           <TabMenu></TabMenu>
           <div
             class={[
@@ -242,18 +270,18 @@ export const useRenderLayout = () => {
               {tagsView.value ? (
                 <TagsView
                   class={[
-                    'border-bottom-1 border-top-1 border-solid border-[var(--tags-view-border-color)] dark:border-[var(--el-border-color)]',
+                    'relative layout-border__bottom layout-border__top',
                     {
                       '!fixed top-0 left-0 z-10': fixedHeader.value,
-                      'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-min-width))] !left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
                         collapse.value && fixedHeader.value,
-                      'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-max-width))] !left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
                         !collapse.value && fixedHeader.value,
-                      '!fixed top-0 left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
+                      '!fixed top-0 !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
                         fixedHeader.value && fixedMenu.value,
-                      'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
                         collapse.value && fixedHeader.value && fixedMenu.value,
-                      'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                      'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] !left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
                         !collapse.value && fixedHeader.value && fixedMenu.value
                     }
                   ]}

+ 1 - 1
src/main.ts

@@ -1,5 +1,5 @@
 // 引入windi css
-import '@/plugins/windi.css'
+import '@/plugins/unocss'
 
 // 导入全局的svg图标
 import '@/plugins/svgIcon'

+ 1 - 0
src/plugins/unocss/index.ts

@@ -0,0 +1 @@
+import 'virtual:uno.css'

+ 0 - 3
src/plugins/windi.css/index.ts

@@ -1,3 +0,0 @@
-import 'virtual:windi.css'
-
-import 'virtual:windi-devtools'

+ 5 - 12
src/styles/var.css

@@ -1,8 +1,5 @@
 :root {
-  --dark-bg-color: #293146;
-
-  /* left menu start */
-  --left-menu-border-color: '#eee';
+  --login-bg-color: #293146;
 
   --left-menu-max-width: 200px;
 
@@ -25,8 +22,6 @@
   --logo-height: 50px;
 
   --logo-title-text-color: #fff;
-
-  --logo-border-color: 'inherit';
   /* logo end */
 
   /* header start */
@@ -40,11 +35,7 @@
 
   --top-tool-p-x: 0;
 
-  --top-tool-border-color: #eee;
-
   --tags-view-height: 35px;
-
-  --tags-view-border-color: #eee;
   /* header start */
 
   /* tab menu start */
@@ -53,8 +44,6 @@
   --tab-menu-min-width: 30px;
 
   --tab-menu-collapse-height: 36px;
-
-  --tab-menu-border-color: #eee;
   /* tab menu end */
 
   --app-content-padding: 20px;
@@ -66,6 +55,10 @@
   --transition-time-02: 0.2s;
 }
 
+.dark {
+  --app-content-bg-color: var(--el-bg-color);
+}
+
 html,
 body {
   -webkit-font-smoothing: antialiased;

+ 2 - 2
src/views/Home/Index.vue

@@ -7,7 +7,7 @@
             <div class="flex items-center">
               <img :src="avatar" alt="" class="w-70px h-70px rounded-[50%] mr-20px" />
               <div>
-                <div class="text-20px text-700">
+                <div class="text-20px">
                   {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
                 </div>
                 <div class="mt-10px text-14px text-gray-500">
@@ -17,7 +17,7 @@
             </div>
           </el-col>
           <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex h-70px items-center justify-end <sm:mt-10px">
+            <div class="flex h-70px items-center justify-end lt-sm:mt-10px">
               <div class="px-8px text-right">
                 <div class="text-14px text-gray-400 mb-20px">{{ t('workplace.project') }}</div>
                 <CountTo

+ 16 - 12
src/views/Login/Login.vue

@@ -1,11 +1,11 @@
 <template>
   <div
     :class="prefixCls"
-    class="h-[100%] relative <xl:bg-v-dark <sm:px-10px <xl:px-10px <md:px-10px"
+    class="h-[100%] relative lt-xl:bg-[var(--login-bg-color)] lt-sm:px-10px lt-xl:px-10px lt-md:px-10px"
   >
     <div class="relative h-full flex mx-auto">
       <div
-        :class="`${prefixCls}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px <xl:hidden`"
+        :class="`${prefixCls}__left flex-1 bg-gray-500 bg-opacity-20 relative p-30px lt-xl:hidden`"
       >
         <!-- 左上角的 logo + 系统标题 -->
         <div class="flex items-center relative text-white">
@@ -27,33 +27,35 @@
           </TransitionGroup>
         </div>
       </div>
-      <div class="flex-1 p-30px <sm:p-10px dark:bg-v-dark relative">
+      <div class="flex-1 p-30px lt-sm:p-10px dark:bg-[var(--login-bg-color)] relative">
         <!-- 右上角的主题、语言选择 -->
-        <div class="flex justify-between items-center text-white @2xl:justify-end @xl:justify-end">
-          <div class="flex items-center @2xl:hidden @xl:hidden">
+        <div
+          class="flex justify-between items-center text-white at-2xl:justify-end at-xl:justify-end"
+        >
+          <div class="flex items-center at-2xl:hidden at-xl:hidden">
             <img alt="" class="w-48px h-48px mr-10px" src="@/assets/imgs/logo.png" />
             <span class="text-20px font-bold">{{ underlineToHump(appStore.getTitle) }}</span>
           </div>
           <div class="flex justify-end items-center space-x-10px">
             <ThemeSwitch />
-            <LocaleDropdown class="<xl:text-white dark:text-white" />
+            <LocaleDropdown class="lt-xl:text-white dark:text-white" />
           </div>
         </div>
         <!-- 右边的登录界面 -->
         <Transition appear enter-active-class="animate__animated animate__bounceInRight">
           <div
-            class="h-full flex items-center m-auto w-[100%] @2xl:max-w-500px @xl:max-w-500px @md:max-w-500px @lg:max-w-500px"
+            class="h-full flex items-center m-auto w-[100%] at-2xl:max-w-500px at-xl:max-w-500px at-md:max-w-500px at-lg:max-w-500px"
           >
             <!-- 账号登录 -->
-            <LoginForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <LoginForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 手机登录 -->
-            <MobileForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <MobileForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 二维码登录 -->
-            <QrCodeForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <QrCodeForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 注册 -->
-            <RegisterForm class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <RegisterForm class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
             <!-- 三方登录 -->
-            <SSOLoginVue class="p-20px h-auto m-auto <xl:(rounded-3xl light:bg-white)" />
+            <SSOLoginVue class="p-20px h-auto m-auto lt-xl:(rounded-3xl light:bg-white)" />
           </div>
         </Transition>
       </div>
@@ -82,6 +84,8 @@ const prefixCls = getPrefixCls('login')
 $prefix-cls: #{$namespace}-login;
 
 .#{$prefix-cls} {
+  overflow: auto;
+
   &__left {
     &::before {
       position: absolute;

+ 2 - 2
tsconfig.json

@@ -10,7 +10,7 @@
     "resolveJsonModule": true,
     "esModuleInterop": true,
     "lib": ["esnext", "dom"],
-    "baseUrl": ".",
+    "baseUrl": "./",
     "allowJs": true,
     "forceConsistentCasingInFileNames": true,
     "allowSyntheticDefaultImports": true,
@@ -36,7 +36,7 @@
     "typeRoots": ["./node_modules/@types/", "./types"]
   },
   "include": [
-    "src/**/*",
+    "src",
     "types/**/*.d.ts",
     "src/types/auto-imports.d.ts",
     "src/types/auto-components.d.ts"

+ 105 - 0
uno.config.ts

@@ -0,0 +1,105 @@
+import { defineConfig, toEscapedSelector as e, presetUno } from 'unocss'
+import transformerVariantGroup from '@unocss/transformer-variant-group'
+
+export default defineConfig({
+  // ...UnoCSS options
+  rules: [
+    [
+      /^custom-hover$/,
+      ([], { rawSelector }) => {
+        const selector = e(rawSelector)
+        return `
+${selector} {
+  display: flex;
+  height: 100%;
+  padding: 1px 10px 0;
+  cursor: pointer;
+  align-items: center;
+  transition: background var(--transition-time-02);
+}
+/* you can have multiple rules */
+${selector}:hover {
+  background-color: var(--top-header-hover-color);
+}
+.dark ${selector}:hover {
+  background-color: var(--el-bg-color-overlay);
+}
+`
+      }
+    ],
+    [
+      /^layout-border__left$/,
+      ([], { rawSelector }) => {
+        const selector = e(rawSelector)
+        return `
+${selector}:before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 1px;
+  height: 100%;
+  background-color: var(--el-border-color);
+  z-index: 3;
+}
+`
+      }
+    ],
+    [
+      /^layout-border__right$/,
+      ([], { rawSelector }) => {
+        const selector = e(rawSelector)
+        return `
+${selector}:after {
+  content: "";
+  position: absolute;
+  top: 0;
+  right: 0;
+  width: 1px;
+  height: 100%;
+  background-color: var(--el-border-color);
+  z-index: 3;
+}
+`
+      }
+    ],
+    [
+      /^layout-border__top$/,
+      ([], { rawSelector }) => {
+        const selector = e(rawSelector)
+        return `
+${selector}:before {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 1px;
+  background-color: var(--el-border-color);
+  z-index: 3;
+}
+`
+      }
+    ],
+    [
+      /^layout-border__bottom$/,
+      ([], { rawSelector }) => {
+        const selector = e(rawSelector)
+        return `
+${selector}:after {
+  content: "";
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 1px;
+  background-color: var(--el-border-color);
+  z-index: 3;
+}
+`
+      }
+    ]
+  ],
+  presets: [presetUno({ dark: 'class', attributify: false })],
+  transformers: [transformerVariantGroup()]
+})

+ 0 - 61
windi.config.ts

@@ -1,61 +0,0 @@
-import { defineConfig } from 'vite-plugin-windicss'
-import plugin from 'windicss/plugin'
-
-function range(size, startAt = 1) {
-  return Array.from(Array(size).keys()).map((i) => i + startAt)
-}
-
-export default defineConfig({
-  extract: {
-    include: ['src/**/*.{vue,html,jsx,tsx}'],
-    exclude: ['node_modules', '.git']
-  },
-  darkMode: 'class',
-  attributify: false,
-  theme: {
-    extend: {
-      backgroundColor: {
-        // 暗黑背景色
-        'v-dark': 'var(--dark-bg-color)'
-      }
-    }
-  },
-  plugins: [
-    plugin(({ addComponents }) => {
-      const obj = {}
-      range(50).map((i) => {
-        obj[`.border-top-${i}`] = {
-          borderTopWidth: `${i}px`
-        }
-        obj[`.border-left-${i}`] = {
-          borderLeftWidth: `${i}px`
-        }
-        obj[`.border-right-${i}`] = {
-          borderRightWidth: `${i}px`
-        }
-        obj[`.border-bottom-${i}`] = {
-          borderBottomWidth: `${i}px`
-        }
-      })
-      addComponents({
-        '.hover-trigger': {
-          display: 'flex',
-          height: '100%',
-          padding: '1px 10px 0',
-          cursor: 'pointer',
-          alignItems: 'center',
-          transition: 'background var(--transition-time-02)',
-          '&:hover': {
-            backgroundColor: 'var(--top-header-hover-color)'
-          }
-        },
-        '.dark .hover-trigger': {
-          '&:hover': {
-            backgroundColor: 'var(--el-bg-color-overlay)'
-          }
-        },
-        ...obj
-      })
-    })
-  ]
-})