Forráskód Böngészése

feat: 升级vue3 v1.8.0

xingyu 2 éve
szülő
commit
7a717ef80d
42 módosított fájl, 181 hozzáadás és 261 törlés
  1. 1 1
      yudao-ui-admin-vue3/package.json
  2. 2 1
      yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue
  3. 1 0
      yudao-ui-admin-vue3/src/components/ContextMenu/src/ContextMenu.vue
  4. 1 0
      yudao-ui-admin-vue3/src/components/Descriptions/src/Descriptions.vue
  5. 1 0
      yudao-ui-admin-vue3/src/components/Form/index.ts
  6. 1 0
      yudao-ui-admin-vue3/src/components/Form/src/Form.vue
  7. 1 0
      yudao-ui-admin-vue3/src/components/Form/src/componentMap.ts
  8. 1 0
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderCheckbox.tsx
  9. 1 0
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderRadio.tsx
  10. 2 0
      yudao-ui-admin-vue3/src/components/Form/src/components/useRenderSelect.tsx
  11. 2 0
      yudao-ui-admin-vue3/src/components/Form/src/helper.ts
  12. 2 0
      yudao-ui-admin-vue3/src/components/Form/src/types.ts
  13. 2 1
      yudao-ui-admin-vue3/src/components/Infotip/src/Infotip.vue
  14. 1 1
      yudao-ui-admin-vue3/src/components/Menu/src/Menu.vue
  15. 1 0
      yudao-ui-admin-vue3/src/components/Qrcode/src/Qrcode.vue
  16. 1 0
      yudao-ui-admin-vue3/src/components/Search/src/Search.vue
  17. 26 1
      yudao-ui-admin-vue3/src/components/Setting/src/components/InterfaceDisplay.vue
  18. 2 1
      yudao-ui-admin-vue3/src/components/SizeDropdown/src/SizeDropdown.vue
  19. 39 9
      yudao-ui-admin-vue3/src/components/TabMenu/src/TabMenu.vue
  20. 4 4
      yudao-ui-admin-vue3/src/components/TabMenu/src/helper.ts
  21. 3 0
      yudao-ui-admin-vue3/src/components/Table/index.ts
  22. 2 0
      yudao-ui-admin-vue3/src/components/Table/src/types.ts
  23. 1 0
      yudao-ui-admin-vue3/src/hooks/web/useConfigGlobal.ts
  24. 3 0
      yudao-ui-admin-vue3/src/hooks/web/useCrudSchemas.ts
  25. 1 0
      yudao-ui-admin-vue3/src/hooks/web/useForm.ts
  26. 1 0
      yudao-ui-admin-vue3/src/hooks/web/useIcon.ts
  27. 8 3
      yudao-ui-admin-vue3/src/hooks/web/useTable.ts
  28. 16 3
      yudao-ui-admin-vue3/src/layout/components/useRenderLayout.tsx
  29. 4 1
      yudao-ui-admin-vue3/src/locales/en.ts
  30. 4 1
      yudao-ui-admin-vue3/src/locales/zh-CN.ts
  31. 17 23
      yudao-ui-admin-vue3/src/store/modules/app.ts
  32. 1 0
      yudao-ui-admin-vue3/src/store/modules/locale.ts
  33. 0 3
      yudao-ui-admin-vue3/types/componentType/configGlobal.d.ts
  34. 0 7
      yudao-ui-admin-vue3/types/componentType/contextMenu.d.ts
  35. 0 11
      yudao-ui-admin-vue3/types/componentType/descriptions.d.ts
  36. 0 97
      yudao-ui-admin-vue3/types/componentType/form.d.ts
  37. 0 5
      yudao-ui-admin-vue3/types/componentType/icon.d.ts
  38. 0 4
      yudao-ui-admin-vue3/types/componentType/infotip.d.ts
  39. 0 10
      yudao-ui-admin-vue3/types/componentType/localeDropdown.d.ts
  40. 0 9
      yudao-ui-admin-vue3/types/componentType/qrcode.d.ts
  41. 0 36
      yudao-ui-admin-vue3/types/componentType/table.d.ts
  42. 28 29
      yudao-ui-admin-vue3/types/global.d.ts

+ 1 - 1
yudao-ui-admin-vue3/package.json

@@ -1,6 +1,6 @@
 {
   "name": "ruoyi-vue-pro-vue3",
-  "version": "1.6.4.1651",
+  "version": "1.6.4.1801",
   "description": "基于vue3、element-plus、typesScript、vite3",
   "author": "xingyu",
   "private": false,

+ 2 - 1
yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue

@@ -7,13 +7,14 @@ import { useWindowSize } from '@vueuse/core'
 import { useAppStore } from '@/store/modules/app'
 import { setCssVar } from '@/utils'
 import { useDesign } from '@/hooks/web/useDesign'
+import { ElementPlusSize } from '@/types/elementPlus'
 
 const { variables } = useDesign()
 
 const appStore = useAppStore()
 
 const props = defineProps({
-  size: propTypes.oneOf<ElememtPlusSize[]>(['default', 'small', 'large']).def('default')
+  size: propTypes.oneOf<ElementPlusSize[]>(['default', 'small', 'large']).def('default')
 })
 
 provide('configGlobal', props)

+ 1 - 0
yudao-ui-admin-vue3/src/components/ContextMenu/src/ContextMenu.vue

@@ -4,6 +4,7 @@ import { PropType, ref } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useDesign } from '@/hooks/web/useDesign'
 import type { RouteLocationNormalizedLoaded } from 'vue-router'
+import { contextMenuSchema } from '../../../types/contextMenu'
 
 const { getPrefixCls } = useDesign()
 

+ 1 - 0
yudao-ui-admin-vue3/src/components/Descriptions/src/Descriptions.vue

@@ -4,6 +4,7 @@ import { useDesign } from '@/hooks/web/useDesign'
 import { propTypes } from '@/utils/propTypes'
 import { ref, unref, PropType, computed, useAttrs } from 'vue'
 import { useAppStore } from '@/store/modules/app'
+import { DescriptionsSchema } from '@/types/descriptions'
 
 const appStore = useAppStore()
 

+ 1 - 0
yudao-ui-admin-vue3/src/components/Form/index.ts

@@ -1,5 +1,6 @@
 import Form from './src/Form.vue'
 import { ElForm } from 'element-plus'
+import { FormSchema, FormSetPropsType } from '@/types/form'
 
 export interface FormExpose {
   setValues: (data: Recordable) => void

+ 1 - 0
yudao-ui-admin-vue3/src/components/Form/src/Form.vue

@@ -20,6 +20,7 @@ import { findIndex } from '@/utils'
 import { set } from 'lodash-es'
 import { FormProps } from './types'
 import { Icon } from '@/components/Icon'
+import { FormSchema, FormSetPropsType } from '@/types/form'
 
 const { getPrefixCls } = useDesign()
 

+ 1 - 0
yudao-ui-admin-vue3/src/components/Form/src/componentMap.ts

@@ -20,6 +20,7 @@ import {
 } from 'element-plus'
 import { InputPassword } from '@/components/InputPassword'
 import { Editor } from '@/components/Editor'
+import { ComponentName } from '@/types/components'
 
 const componentMap: Recordable<Component, ComponentName> = {
   Radio: ElRadioGroup,

+ 1 - 0
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderCheckbox.tsx

@@ -1,3 +1,4 @@
+import { FormSchema } from '@/types/form'
 import { ElCheckbox, ElCheckboxButton } from 'element-plus'
 import { defineComponent } from 'vue'
 

+ 1 - 0
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderRadio.tsx

@@ -1,3 +1,4 @@
+import { FormSchema } from '@/types/form'
 import { ElRadio, ElRadioButton } from 'element-plus'
 import { defineComponent } from 'vue'
 

+ 2 - 0
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderSelect.tsx

@@ -1,3 +1,5 @@
+import { FormSchema } from '@/types/form'
+import { ComponentOptions } from '@/types/components'
 import { ElOption, ElOptionGroup } from 'element-plus'
 import { getSlot } from '@/utils/tsxHelper'
 import { Slots } from 'vue'

+ 2 - 0
yudao-ui-admin-vue3/src/components/Form/src/helper.ts

@@ -2,6 +2,8 @@ import { useI18n } from '@/hooks/web/useI18n'
 import type { Slots } from 'vue'
 import { getSlot } from '@/utils/tsxHelper'
 import { PlaceholderMoel } from './types'
+import { FormSchema } from '@/types/form'
+import { ColProps } from '@/types/components'
 
 /**
  *

+ 2 - 0
yudao-ui-admin-vue3/src/components/Form/src/types.ts

@@ -1,3 +1,5 @@
+import { FormSchema } from '@/types/form'
+
 export interface PlaceholderMoel {
   placeholder?: string
   startPlaceholder?: string

+ 2 - 1
yudao-ui-admin-vue3/src/components/Infotip/src/Infotip.vue

@@ -1,8 +1,9 @@
 <script setup lang="ts">
 import { PropType } from 'vue'
-import { Highlight } from '@//components/Highlight'
+import { Highlight } from '@/components/Highlight'
 import { useDesign } from '@/hooks/web/useDesign'
 import { propTypes } from '@/utils/propTypes'
+import { TipSchema } from '@/types/infoTip'
 
 const { getPrefixCls } = useDesign()
 

+ 1 - 1
yudao-ui-admin-vue3/src/components/Menu/src/Menu.vue

@@ -3,11 +3,11 @@ import { computed, defineComponent, unref, PropType } from 'vue'
 import { ElMenu, ElScrollbar } from 'element-plus'
 import { useAppStore } from '@/store/modules/app'
 import { usePermissionStore } from '@/store/modules/permission'
-import type { LayoutType } from '@/config/app'
 import { useRenderMenuItem } from './components/useRenderMenuItem'
 import { useRouter } from 'vue-router'
 import { isUrl } from '@/utils/is'
 import { useDesign } from '@/hooks/web/useDesign'
+import { LayoutType } from '@/types/layout'
 
 const { getPrefixCls } = useDesign()
 

+ 1 - 0
yudao-ui-admin-vue3/src/components/Qrcode/src/Qrcode.vue

@@ -6,6 +6,7 @@ import { cloneDeep } from 'lodash-es'
 import { propTypes } from '@/utils/propTypes'
 import { useDesign } from '@/hooks/web/useDesign'
 import { isString } from '@/utils/is'
+import { QrcodeLogo } from '@/types/qrcode'
 
 const props = defineProps({
   // img 或者 canvas,img不支持logo嵌套

+ 1 - 0
yudao-ui-admin-vue3/src/components/Search/src/Search.vue

@@ -7,6 +7,7 @@ import { useI18n } from '@/hooks/web/useI18n'
 import { useForm } from '@/hooks/web/useForm'
 import { findIndex } from '@/utils'
 import { cloneDeep } from 'lodash-es'
+import { FormSchema } from '@/types/form'
 
 const { t } = useI18n()
 

+ 26 - 1
yudao-ui-admin-vue3/src/components/Setting/src/components/InterfaceDisplay.vue

@@ -1,5 +1,5 @@
 <script setup lang="ts">
-import { ElSwitch } from 'element-plus'
+import { ElSwitch, ElMessage } from 'element-plus'
 import { useI18n } from '@/hooks/web/useI18n'
 import { useAppStore } from '@/store/modules/app'
 import { computed, ref, watch } from 'vue'
@@ -107,6 +107,21 @@ const greyModeChange = (show: boolean) => {
   appStore.setGreyMode(show)
 }
 
+// 动态路由
+const dynamicRouter = ref(appStore.getDynamicRouter)
+
+const dynamicRouterChange = (show: boolean) => {
+  ElMessage.info(t('setting.reExperienced'))
+  appStore.setDynamicRouter(show)
+}
+
+// 固定菜单
+const fixedMenu = ref(appStore.getFixedMenu)
+
+const fixedMenuChange = (show: boolean) => {
+  appStore.setFixedMenu(show)
+}
+
 const layout = computed(() => appStore.getLayout)
 
 watch(
@@ -185,5 +200,15 @@ watch(
       <span class="text-14px">{{ t('setting.greyMode') }}</span>
       <ElSwitch v-model="greyMode" @change="greyModeChange" />
     </div>
+
+    <div class="flex justify-between items-center">
+      <span class="text-14px">{{ t('setting.dynamicRouter') }}</span>
+      <ElSwitch v-model="dynamicRouter" @change="dynamicRouterChange" />
+    </div>
+
+    <div class="flex justify-between items-center">
+      <span class="text-14px">{{ t('setting.fixedMenu') }}</span>
+      <ElSwitch v-model="fixedMenu" @change="fixedMenuChange" />
+    </div>
   </div>
 </template>

+ 2 - 1
yudao-ui-admin-vue3/src/components/SizeDropdown/src/SizeDropdown.vue

@@ -5,6 +5,7 @@ import { useAppStore } from '@/store/modules/app'
 import { useI18n } from '@/hooks/web/useI18n'
 import { propTypes } from '@/utils/propTypes'
 import { useDesign } from '@/hooks/web/useDesign'
+import { ElementPlusSize } from '@/types/elementPlus'
 
 const { getPrefixCls } = useDesign()
 
@@ -20,7 +21,7 @@ const appStore = useAppStore()
 
 const sizeMap = computed(() => appStore.sizeMap)
 
-const setCurrentSize = (size: ElememtPlusSize) => {
+const setCurrentSize = (size: ElementPlusSize) => {
   appStore.setCurrentSize(size)
 }
 </script>

+ 39 - 9
yudao-ui-admin-vue3/src/components/TabMenu/src/TabMenu.vue

@@ -1,7 +1,7 @@
 <script lang="tsx">
 import { usePermissionStore } from '@/store/modules/permission'
 import { useAppStore } from '@/store/modules/app'
-import { computed, unref, defineComponent, watch, ref } from 'vue'
+import { computed, unref, defineComponent, watch, ref, onMounted } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { ElScrollbar } from 'element-plus'
 import { Icon } from '@/components/Icon'
@@ -28,6 +28,8 @@ export default defineComponent({
 
     const collapse = computed(() => appStore.getCollapse)
 
+    const fixedMenu = computed(() => appStore.getFixedMenu)
+
     const permissionStore = usePermissionStore()
 
     const routers = computed(() => permissionStore.getRouters)
@@ -38,6 +40,27 @@ export default defineComponent({
       appStore.setCollapse(!unref(collapse))
     }
 
+    onMounted(() => {
+      if (unref(fixedMenu)) {
+        const path = `/${unref(currentRoute).path.split('/')[1]}`
+        const children = unref(tabRouters).find(
+          (v) =>
+            (v.meta?.alwaysShow || (v?.children?.length && v?.children?.length > 1)) &&
+            v.path === path
+        )?.children
+
+        tabActive.value = path
+        if (children) {
+          permissionStore.setMenuTabRouters(
+            cloneDeep(children).map((v) => {
+              v.path = pathResolve(unref(tabActive), v.path)
+              return v
+            })
+          )
+        }
+      }
+    })
+
     watch(
       () => routers.value,
       (routers: AppRouteRecordRaw[]) => {
@@ -55,6 +78,9 @@ export default defineComponent({
     watch(
       () => collapse.value,
       (collapse: boolean) => {
+        if (unref(fixedMenu)) {
+          return
+        }
         if (!collapse) {
           setTimeout(() => {
             showTitle.value = !collapse
@@ -66,7 +92,7 @@ export default defineComponent({
     )
 
     // 是否显示菜单
-    const showMenu = ref(false)
+    const showMenu = ref(unref(fixedMenu) ? true : false)
 
     // tab高亮
     const tabActive = ref('')
@@ -77,9 +103,13 @@ export default defineComponent({
         window.open(item.path)
         return
       }
+      const newPath = item.children ? item.path : item.path.split('/')[0]
+      const oldPath = unref(tabActive)
       tabActive.value = item.children ? item.path : item.path.split('/')[0]
       if (item.children) {
-        showMenu.value = !unref(showMenu)
+        if (newPath === oldPath || !unref(showMenu)) {
+          showMenu.value = unref(fixedMenu) ? true : !unref(showMenu)
+        }
         if (unref(showMenu)) {
           permissionStore.setMenuTabRouters(
             cloneDeep(item.children).map((v) => {
@@ -96,7 +126,7 @@ export default defineComponent({
     }
 
     // 设置高亮
-    const isActice = (currentPath: string) => {
+    const isActive = (currentPath: string) => {
       const { path } = unref(currentRoute)
       if (tabPathMap[currentPath].includes(path)) {
         return true
@@ -105,7 +135,7 @@ export default defineComponent({
     }
 
     const mouseleave = () => {
-      if (!unref(showMenu)) return
+      if (!unref(showMenu) || unref(fixedMenu)) return
       showMenu.value = false
     }
 
@@ -114,7 +144,7 @@ export default defineComponent({
         id={`${variables.namespace}-menu`}
         class={[
           prefixCls,
-          'relative bg-[var(--left-menu-bg-color)] top-1px z-999',
+          'relative bg-[var(--left-menu-bg-color)] top-1px z-99999',
           {
             'w-[var(--tab-menu-max-width)]': !unref(collapse),
             'w-[var(--tab-menu-min-width)]': unref(collapse)
@@ -140,7 +170,7 @@ export default defineComponent({
                       `${prefixCls}__item`,
                       'text-center text-12px relative py-12px cursor-pointer',
                       {
-                        'is-active': isActice(v.path)
+                        'is-active': isActive(v.path)
                       }
                     ]}
                     onClick={() => {
@@ -174,8 +204,8 @@ export default defineComponent({
             {
               '!left-[var(--tab-menu-min-width)]': unref(collapse),
               '!left-[var(--tab-menu-max-width)]': !unref(collapse),
-              '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu),
-              '!w-0': !unref(showMenu)
+              '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu) || unref(fixedMenu),
+              '!w-0': !unref(showMenu) && !unref(fixedMenu)
             }
           ]}
           style="transition: width var(--transition-time-02), left var(--transition-time-02);"

+ 4 - 4
yudao-ui-admin-vue3/src/components/TabMenu/src/helper.ts

@@ -28,9 +28,9 @@ export const filterMenusPath = (
     let data: Nullable<AppRouteRecordRaw> = null
     const meta = (v.meta ?? {}) as RouteMeta
     if (!meta.hidden || meta.canTo) {
-      const allParentPaht = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path)
+      const allParentPath = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path)
 
-      const fullPath = isUrl(v.path) ? v.path : allParentPaht.join('/')
+      const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/')
 
       data = cloneDeep(v)
       data.path = fullPath
@@ -42,8 +42,8 @@ export const filterMenusPath = (
         res.push(data)
       }
 
-      if (allParentPaht.length && Reflect.has(tabPathMap, allParentPaht[0])) {
-        tabPathMap[allParentPaht[0]].push(fullPath)
+      if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) {
+        tabPathMap[allParentPath[0]].push(fullPath)
       }
     }
   }

+ 3 - 0
yudao-ui-admin-vue3/src/components/Table/index.ts

@@ -1,9 +1,12 @@
 import Table from './src/Table.vue'
+import { ElTable } from 'element-plus'
+import { TableSetPropsType } from '@/types/table'
 
 export interface TableExpose {
   setProps: (props: Recordable) => void
   setColumn: (columnProps: TableSetPropsType[]) => void
   selections: Recordable[]
+  elTableRef: ComponentRef<typeof ElTable>
 }
 
 export { Table }

+ 2 - 0
yudao-ui-admin-vue3/src/components/Table/src/types.ts

@@ -1,3 +1,5 @@
+import { Pagination, TableColumn } from '@/types/table'
+
 export type TableProps = {
   pageSize?: number
   currentPage?: number

+ 1 - 0
yudao-ui-admin-vue3/src/hooks/web/useConfigGlobal.ts

@@ -1,3 +1,4 @@
+import { ConfigGlobalTypes } from '@/types/configGlobal'
 import { inject } from 'vue'
 
 export const useConfigGlobal = () => {

+ 3 - 0
yudao-ui-admin-vue3/src/hooks/web/useCrudSchemas.ts

@@ -1,6 +1,9 @@
 import { reactive } from 'vue'
 import { eachTree, treeMap, filter } from '@/utils/tree'
 import { getIntDictOptions } from '@/utils/dict'
+import { FormSchema } from '@/types/form'
+import { TableColumn } from '@/types/table'
+import { DescriptionsSchema } from '@/types/descriptions'
 
 export type CrudSchema = Omit<TableColumn, 'children'> & {
   search?: CrudSearchParams

+ 1 - 0
yudao-ui-admin-vue3/src/hooks/web/useForm.ts

@@ -2,6 +2,7 @@ import type { Form, FormExpose } from '@/components/Form'
 import type { ElForm } from 'element-plus'
 import { ref, unref, nextTick } from 'vue'
 import type { FormProps } from '@/components/Form/src/types'
+import { FormSchema, FormSetPropsType } from '@/types/form'
 
 export const useForm = (props?: FormProps) => {
   // From实例

+ 1 - 0
yudao-ui-admin-vue3/src/hooks/web/useIcon.ts

@@ -1,6 +1,7 @@
 import { h } from 'vue'
 import type { VNode } from 'vue'
 import { Icon } from '@/components/Icon'
+import { IconTypes } from '@/types/icon'
 
 export const useIcon = (props: IconTypes): VNode => {
   return h(Icon, props)

+ 8 - 3
yudao-ui-admin-vue3/src/hooks/web/useTable.ts

@@ -4,6 +4,7 @@ import { ElMessage, ElMessageBox, ElTable } from 'element-plus'
 import { computed, nextTick, reactive, ref, unref, watch } from 'vue'
 import type { TableProps } from '@/components/Table/src/types'
 import { useI18n } from '@/hooks/web/useI18n'
+import { TableSetPropsType } from '@/types/table'
 
 const { t } = useI18n()
 interface ResponseType<T = any> {
@@ -150,13 +151,17 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => {
     },
     // 与Search组件结合
     setSearchParams: (data: Recordable) => {
-      tableObject.currentPage = 1
       tableObject.params = Object.assign(tableObject.params, {
         pageSize: tableObject.pageSize,
-        pageNo: tableObject.currentPage,
+        pageNo: 1,
         ...data
       })
-      methods.getList()
+      // 页码不等于1时更新页码重新获取数据,页码等于1时重新获取数据
+      if (tableObject.currentPage !== 1) {
+        tableObject.currentPage = 1
+      } else {
+        methods.getList()
+      }
     },
     // 删除数据
     delList: async (

+ 16 - 3
yudao-ui-admin-vue3/src/layout/components/useRenderLayout.tsx

@@ -32,6 +32,9 @@ const fixedHeader = computed(() => appStore.getFixedHeader)
 // 是否是移动端
 const mobile = computed(() => appStore.getMobile)
 
+// 固定菜单
+const fixedMenu = computed(() => appStore.getFixedMenu)
+
 export const useRenderLayout = () => {
   const renderClassic = () => {
     return (
@@ -213,9 +216,13 @@ export const useRenderLayout = () => {
               'h-[100%]',
               {
                 'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]':
-                  collapse.value,
+                  collapse.value && !fixedMenu.value,
                 'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)]':
-                  !collapse.value
+                  !collapse.value && !fixedMenu.value,
+                'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]':
+                  collapse.value && fixedMenu.value,
+                'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]':
+                  !collapse.value && fixedMenu.value
               }
             ]}
             style="transition: all var(--transition-time-02);"
@@ -239,7 +246,13 @@ export const useRenderLayout = () => {
                       '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)]':
-                        !collapse.value && fixedHeader.value
+                        !collapse.value && fixedHeader.value,
+                      '!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)]':
+                        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)]':
+                        !collapse.value && fixedHeader.value && fixedMenu.value
                     }
                   ]}
                   style="transition: width var(--transition-time-02), left var(--transition-time-02);"

+ 4 - 1
yudao-ui-admin-vue3/src/locales/en.ts

@@ -91,7 +91,10 @@ export default {
     copyFailed: 'Copy failed',
     footer: 'Footer',
     uniqueOpened: 'Unique opened',
-    tagsViewIcon: 'Tags view icon'
+    tagsViewIcon: 'Tags view icon',
+    dynamicRouter: 'Dynamic router',
+    reExperienced: 'Please exit the login experience again',
+    fixedMenu: 'Fixed menu'
   },
   size: {
     default: 'Default',

+ 4 - 1
yudao-ui-admin-vue3/src/locales/zh-CN.ts

@@ -91,7 +91,10 @@ export default {
     copyFailed: '拷贝失败',
     footer: '页脚',
     uniqueOpened: '菜单手风琴',
-    tagsViewIcon: '标签页图标'
+    tagsViewIcon: '标签页图标',
+    dynamicRouter: '动态路由',
+    reExperienced: '请重新退出登录体验',
+    fixedMenu: '固定菜单'
   },
   size: {
     default: '默认',

+ 17 - 23
yudao-ui-admin-vue3/src/store/modules/app.ts

@@ -3,27 +3,12 @@ import { store } from '../index'
 import { setCssVar, humpToUnderline } from '@/utils'
 import { ElMessage } from 'element-plus'
 import { useCache } from '@/hooks/web/useCache'
+import { ElementPlusSize } from '@/types/elementPlus'
+import { LayoutType } from '@/types/layout'
+import { ThemeTypes } from '@/types/theme'
 
 const { wsCache } = useCache()
 
-type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu'
-
-type ThemeTypes = {
-  elColorPrimary?: string
-  leftMenuBorderColor?: string
-  leftMenuBgColor?: string
-  leftMenuBgLightColor?: string
-  leftMenuBgActiveColor?: string
-  leftMenuCollapseBgActiveColor?: string
-  leftMenuTextColor?: string
-  leftMenuTextActiveColor?: string
-  logoTitleTextColor?: string
-  logoBorderColor?: string
-  topHeaderBgColor?: string
-  topHeaderTextColor?: string
-  topHeaderHoverColor?: string
-  topToolBorderColor?: string
-}
 interface AppState {
   breadcrumb: boolean
   breadcrumbIcon: boolean
@@ -43,11 +28,12 @@ interface AppState {
   title: string
   userInfo: string
   isDark: boolean
-  currentSize: ElememtPlusSize
-  sizeMap: ElememtPlusSize[]
+  currentSize: ElementPlusSize
+  sizeMap: ElementPlusSize[]
   mobile: boolean
   footer: boolean
   theme: ThemeTypes
+  fixedMenu: boolean
 }
 
 export const useAppStore = defineStore('app', {
@@ -73,6 +59,7 @@ export const useAppStore = defineStore('app', {
       fixedHeader: true, // 固定toolheader
       footer: true, // 显示页脚
       greyMode: false, // 是否开始灰色模式,用于特殊悼念日
+      fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
 
       layout: wsCache.get('layout') || 'classic', // layout布局
       isDark: wsCache.get('isDark') || false, // 是否是暗黑模式
@@ -149,6 +136,9 @@ export const useAppStore = defineStore('app', {
     getGreyMode(): boolean {
       return this.greyMode
     },
+    getFixedMenu(): boolean {
+      return this.fixedMenu
+    },
     getPageLoading(): boolean {
       return this.pageLoading
     },
@@ -164,10 +154,10 @@ export const useAppStore = defineStore('app', {
     getIsDark(): boolean {
       return this.isDark
     },
-    getCurrentSize(): ElememtPlusSize {
+    getCurrentSize(): ElementPlusSize {
       return this.currentSize
     },
-    getSizeMap(): ElememtPlusSize[] {
+    getSizeMap(): ElementPlusSize[] {
       return this.sizeMap
     },
     getMobile(): boolean {
@@ -220,6 +210,10 @@ export const useAppStore = defineStore('app', {
     setGreyMode(greyMode: boolean) {
       this.greyMode = greyMode
     },
+    setFixedMenu(fixedMenu: boolean) {
+      wsCache.set('fixedMenu', fixedMenu)
+      this.fixedMenu = fixedMenu
+    },
     setPageLoading(pageLoading: boolean) {
       this.pageLoading = pageLoading
     },
@@ -245,7 +239,7 @@ export const useAppStore = defineStore('app', {
       }
       wsCache.set('isDark', this.isDark)
     },
-    setCurrentSize(currentSize: ElememtPlusSize) {
+    setCurrentSize(currentSize: ElementPlusSize) {
       this.currentSize = currentSize
       wsCache.set('currentSize', this.currentSize)
     },

+ 1 - 0
yudao-ui-admin-vue3/src/store/modules/locale.ts

@@ -3,6 +3,7 @@ import { store } from '../index'
 import zhCn from 'element-plus/es/locale/lang/zh-cn'
 import en from 'element-plus/es/locale/lang/en'
 import { useCache } from '@/hooks/web/useCache'
+import { LocaleDropdownType } from '@/types/localeDropdown'
 
 const { wsCache } = useCache()
 

+ 0 - 3
yudao-ui-admin-vue3/types/componentType/configGlobal.d.ts

@@ -1,3 +0,0 @@
-declare interface ConfigGlobalTypes {
-  size?: ElememtPlusSize
-}

+ 0 - 7
yudao-ui-admin-vue3/types/componentType/contextMenu.d.ts

@@ -1,7 +0,0 @@
-declare type contextMenuSchema = {
-  disabled?: boolean
-  divided?: boolean
-  icon?: string
-  label: string
-  command?: (item: contextMenuSchema) => viod
-}

+ 0 - 11
yudao-ui-admin-vue3/types/componentType/descriptions.d.ts

@@ -1,11 +0,0 @@
-declare interface DescriptionsSchema {
-  span?: number // 占多少分
-  field: string // 字段名
-  label?: string // label名
-  width?: string | number
-  minWidth?: string | number
-  align?: 'left' | 'center' | 'right'
-  labelAlign?: 'left' | 'center' | 'right'
-  className?: string
-  labelClassName?: string
-}

+ 0 - 97
yudao-ui-admin-vue3/types/componentType/form.d.ts

@@ -1,97 +0,0 @@
-import type { CSSProperties } from 'vue'
-
-declare global {
-  declare type ComponentName =
-    | 'Radio'
-    | 'RadioButton'
-    | 'Checkbox'
-    | 'CheckboxButton'
-    | 'Input'
-    | 'Autocomplete'
-    | 'InputNumber'
-    | 'Select'
-    | 'Cascader'
-    | 'Switch'
-    | 'Slider'
-    | 'TimePicker'
-    | 'DatePicker'
-    | 'Rate'
-    | 'ColorPicker'
-    | 'Transfer'
-    | 'Divider'
-    | 'TimeSelect'
-    | 'SelectV2'
-    | 'InputPassword'
-    | 'Editor'
-
-  declare type ColProps = {
-    span?: number
-    xs?: number
-    sm?: number
-    md?: number
-    lg?: number
-    xl?: number
-    tag?: string
-  }
-
-  declare type FormValueType = string | number | string[] | number[] | boolean | undefined | null
-
-  declare type FormItemProps = {
-    labelWidth?: string | number
-    required?: boolean
-    rules?: Recordable
-    error?: string
-    showMessage?: boolean
-    inlineMessage?: boolean
-    style?: CSSProperties
-  }
-
-  declare type ComponentOptions = {
-    label?: string
-    value?: FormValueType
-    disabled?: boolean
-    key?: string | number
-    children?: ComponentOptions[]
-    options?: ComponentOptions[]
-  } & Recordable
-
-  declare type ComponentOptionsAlias = {
-    labelField?: string
-    valueField?: string
-  }
-
-  declare type ComponentProps = {
-    optionsAlias?: ComponentOptionsAlias
-    options?: ComponentOptions[]
-    optionsSlot?: boolean
-  } & Recordable
-
-  declare type FormSchema = {
-    // 唯一值
-    field: string
-    // 标题
-    label?: string
-    // 提示
-    labelMessage?: string
-    // col组件属性
-    colProps?: ColProps
-    // 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档
-    componentProps?: { slots?: Recordable } & ComponentProps
-    // formItem组件属性
-    formItemProps?: FormItemProps
-    // 渲染的组件
-    component?: ComponentName
-    // 初始值
-    value?: FormValueType
-    // 是否隐藏
-    hidden?: boolean
-    // 远程加载下拉项
-    api?: <T = any>() => Promise<T>
-  }
-
-  declare type FormSetPropsType = {
-    field: string
-    path: string
-    value: any
-  }
-}

+ 0 - 5
yudao-ui-admin-vue3/types/componentType/icon.d.ts

@@ -1,5 +0,0 @@
-declare interface IconTypes {
-  size?: number
-  color?: string
-  icon: string
-}

+ 0 - 4
yudao-ui-admin-vue3/types/componentType/infotip.d.ts

@@ -1,4 +0,0 @@
-declare interface TipSchema {
-  label: string
-  keys?: string[]
-}

+ 0 - 10
yudao-ui-admin-vue3/types/componentType/localeDropdown.d.ts

@@ -1,10 +0,0 @@
-declare interface Language {
-  el: Recordable
-  name: string
-}
-
-declare interface LocaleDropdownType {
-  lang: LocaleType
-  name?: string
-  elLocale?: Language
-}

+ 0 - 9
yudao-ui-admin-vue3/types/componentType/qrcode.d.ts

@@ -1,9 +0,0 @@
-declare interface QrcodeLogo {
-  src?: string
-  logoSize?: number
-  bgColor?: string
-  borderSize?: number
-  crossOrigin?: string
-  borderRadius?: number
-  logoRadius?: number
-}

+ 0 - 36
yudao-ui-admin-vue3/types/componentType/table.d.ts

@@ -1,36 +0,0 @@
-declare type TableColumn = {
-  field: string
-  label?: string
-  children?: TableColumn[]
-} & Recordable
-
-declare type TableSlotDefault = {
-  row: Recordable
-  column: TableColumn
-  $index: number
-} & Recordable
-
-declare interface Pagination {
-  small?: boolean
-  background?: boolean
-  pageSize?: number
-  defaultPageSize?: number
-  total?: number
-  pageCount?: number
-  pagerCount?: number
-  currentPage?: number
-  defaultCurrentPage?: number
-  layout?: string
-  pageSizes?: number[]
-  popperClass?: string
-  prevText?: string
-  nextText?: string
-  disabled?: boolean
-  hideOnSinglePage?: boolean
-}
-
-declare interface TableSetPropsType {
-  field: string
-  path: string
-  value: any
-}

+ 28 - 29
yudao-ui-admin-vue3/types/global.d.ts

@@ -1,40 +1,39 @@
-declare interface Fn<T = any> {
-  (...arg: T[]): T
-}
-
-declare type Nullable<T> = T | null
+import type { CSSProperties } from 'vue'
+declare global {
+  declare interface Fn<T = any> {
+    (...arg: T[]): T
+  }
 
-declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>
+  declare type Nullable<T> = T | null
 
-declare type ElememtPlusSize = 'default' | 'small' | 'large'
+  declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T>
 
-declare type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger'
+  declare type Recordable<T = any, K = string> = Record<K extends null | undefined ? string : K, T>
 
-declare type Recordable<T = any, K = string> = Record<K extends null | undefined ? string : K, T>
+  declare type ComponentRef<T> = InstanceType<T>
 
-declare type ComponentRef<T> = InstanceType<T>
+  declare type LocaleType = 'zh-CN' | 'en'
 
-declare type LocaleType = 'zh-CN' | 'en'
+  declare type AxiosHeaders =
+    | 'application/json'
+    | 'application/x-www-form-urlencoded'
+    | 'multipart/form-data'
 
-declare type AxiosHeaders =
-  | 'application/json'
-  | 'application/x-www-form-urlencoded'
-  | 'multipart/form-data'
+  declare type AxiosMethod = 'get' | 'post' | 'delete' | 'put'
 
-declare type AxiosMethod = 'GET' | 'POST' | 'DELETE' | 'PUT'
+  declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
 
-declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
-
-declare interface AxiosConfig {
-  params?: any
-  data?: any
-  url?: string
-  method?: AxiosMethod
-  headersType?: string
-  responseType?: AxiosResponseType
-}
+  declare interface AxiosConfig {
+    params?: any
+    data?: any
+    url?: string
+    method?: AxiosMethod
+    headersType?: string
+    responseType?: AxiosResponseType
+  }
 
-declare interface IResponse<T = any> {
-  code?: number
-  data: T extends any ? T : T & any
+  declare interface IResponse<T = any> {
+    code: string
+    data: T extends any ? T : T & any
+  }
 }