Commit 7a717ef80dd2da1c2f25f25391b96f71ca190fe3
1 parent
a98af3ed
feat: 升级vue3 v1.8.0
Showing
42 changed files
with
181 additions
and
261 deletions
yudao-ui-admin-vue3/package.json
yudao-ui-admin-vue3/src/components/ConfigGlobal/src/ConfigGlobal.vue
| ... | ... | @@ -7,13 +7,14 @@ import { useWindowSize } from '@vueuse/core' |
| 7 | 7 | import { useAppStore } from '@/store/modules/app' |
| 8 | 8 | import { setCssVar } from '@/utils' |
| 9 | 9 | import { useDesign } from '@/hooks/web/useDesign' |
| 10 | +import { ElementPlusSize } from '@/types/elementPlus' | |
| 10 | 11 | |
| 11 | 12 | const { variables } = useDesign() |
| 12 | 13 | |
| 13 | 14 | const appStore = useAppStore() |
| 14 | 15 | |
| 15 | 16 | const props = defineProps({ |
| 16 | - size: propTypes.oneOf<ElememtPlusSize[]>(['default', 'small', 'large']).def('default') | |
| 17 | + size: propTypes.oneOf<ElementPlusSize[]>(['default', 'small', 'large']).def('default') | |
| 17 | 18 | }) |
| 18 | 19 | |
| 19 | 20 | provide('configGlobal', props) | ... | ... |
yudao-ui-admin-vue3/src/components/ContextMenu/src/ContextMenu.vue
| ... | ... | @@ -4,6 +4,7 @@ import { PropType, ref } from 'vue' |
| 4 | 4 | import { useI18n } from '@/hooks/web/useI18n' |
| 5 | 5 | import { useDesign } from '@/hooks/web/useDesign' |
| 6 | 6 | import type { RouteLocationNormalizedLoaded } from 'vue-router' |
| 7 | +import { contextMenuSchema } from '../../../types/contextMenu' | |
| 7 | 8 | |
| 8 | 9 | const { getPrefixCls } = useDesign() |
| 9 | 10 | ... | ... |
yudao-ui-admin-vue3/src/components/Descriptions/src/Descriptions.vue
| ... | ... | @@ -4,6 +4,7 @@ import { useDesign } from '@/hooks/web/useDesign' |
| 4 | 4 | import { propTypes } from '@/utils/propTypes' |
| 5 | 5 | import { ref, unref, PropType, computed, useAttrs } from 'vue' |
| 6 | 6 | import { useAppStore } from '@/store/modules/app' |
| 7 | +import { DescriptionsSchema } from '@/types/descriptions' | |
| 7 | 8 | |
| 8 | 9 | const appStore = useAppStore() |
| 9 | 10 | ... | ... |
yudao-ui-admin-vue3/src/components/Form/index.ts
yudao-ui-admin-vue3/src/components/Form/src/Form.vue
| ... | ... | @@ -20,6 +20,7 @@ import { findIndex } from '@/utils' |
| 20 | 20 | import { set } from 'lodash-es' |
| 21 | 21 | import { FormProps } from './types' |
| 22 | 22 | import { Icon } from '@/components/Icon' |
| 23 | +import { FormSchema, FormSetPropsType } from '@/types/form' | |
| 23 | 24 | |
| 24 | 25 | const { getPrefixCls } = useDesign() |
| 25 | 26 | ... | ... |
yudao-ui-admin-vue3/src/components/Form/src/componentMap.ts
| ... | ... | @@ -20,6 +20,7 @@ import { |
| 20 | 20 | } from 'element-plus' |
| 21 | 21 | import { InputPassword } from '@/components/InputPassword' |
| 22 | 22 | import { Editor } from '@/components/Editor' |
| 23 | +import { ComponentName } from '@/types/components' | |
| 23 | 24 | |
| 24 | 25 | const componentMap: Recordable<Component, ComponentName> = { |
| 25 | 26 | Radio: ElRadioGroup, | ... | ... |
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderCheckbox.tsx
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderRadio.tsx
yudao-ui-admin-vue3/src/components/Form/src/components/useRenderSelect.tsx
yudao-ui-admin-vue3/src/components/Form/src/helper.ts
| ... | ... | @@ -2,6 +2,8 @@ import { useI18n } from '@/hooks/web/useI18n' |
| 2 | 2 | import type { Slots } from 'vue' |
| 3 | 3 | import { getSlot } from '@/utils/tsxHelper' |
| 4 | 4 | import { PlaceholderMoel } from './types' |
| 5 | +import { FormSchema } from '@/types/form' | |
| 6 | +import { ColProps } from '@/types/components' | |
| 5 | 7 | |
| 6 | 8 | /** |
| 7 | 9 | * | ... | ... |
yudao-ui-admin-vue3/src/components/Form/src/types.ts
yudao-ui-admin-vue3/src/components/Infotip/src/Infotip.vue
| 1 | 1 | <script setup lang="ts"> |
| 2 | 2 | import { PropType } from 'vue' |
| 3 | -import { Highlight } from '@//components/Highlight' | |
| 3 | +import { Highlight } from '@/components/Highlight' | |
| 4 | 4 | import { useDesign } from '@/hooks/web/useDesign' |
| 5 | 5 | import { propTypes } from '@/utils/propTypes' |
| 6 | +import { TipSchema } from '@/types/infoTip' | |
| 6 | 7 | |
| 7 | 8 | const { getPrefixCls } = useDesign() |
| 8 | 9 | ... | ... |
yudao-ui-admin-vue3/src/components/Menu/src/Menu.vue
| ... | ... | @@ -3,11 +3,11 @@ import { computed, defineComponent, unref, PropType } from 'vue' |
| 3 | 3 | import { ElMenu, ElScrollbar } from 'element-plus' |
| 4 | 4 | import { useAppStore } from '@/store/modules/app' |
| 5 | 5 | import { usePermissionStore } from '@/store/modules/permission' |
| 6 | -import type { LayoutType } from '@/config/app' | |
| 7 | 6 | import { useRenderMenuItem } from './components/useRenderMenuItem' |
| 8 | 7 | import { useRouter } from 'vue-router' |
| 9 | 8 | import { isUrl } from '@/utils/is' |
| 10 | 9 | import { useDesign } from '@/hooks/web/useDesign' |
| 10 | +import { LayoutType } from '@/types/layout' | |
| 11 | 11 | |
| 12 | 12 | const { getPrefixCls } = useDesign() |
| 13 | 13 | ... | ... |
yudao-ui-admin-vue3/src/components/Qrcode/src/Qrcode.vue
| ... | ... | @@ -6,6 +6,7 @@ import { cloneDeep } from 'lodash-es' |
| 6 | 6 | import { propTypes } from '@/utils/propTypes' |
| 7 | 7 | import { useDesign } from '@/hooks/web/useDesign' |
| 8 | 8 | import { isString } from '@/utils/is' |
| 9 | +import { QrcodeLogo } from '@/types/qrcode' | |
| 9 | 10 | |
| 10 | 11 | const props = defineProps({ |
| 11 | 12 | // img 或者 canvas,img不支持logo嵌套 | ... | ... |
yudao-ui-admin-vue3/src/components/Search/src/Search.vue
| ... | ... | @@ -7,6 +7,7 @@ import { useI18n } from '@/hooks/web/useI18n' |
| 7 | 7 | import { useForm } from '@/hooks/web/useForm' |
| 8 | 8 | import { findIndex } from '@/utils' |
| 9 | 9 | import { cloneDeep } from 'lodash-es' |
| 10 | +import { FormSchema } from '@/types/form' | |
| 10 | 11 | |
| 11 | 12 | const { t } = useI18n() |
| 12 | 13 | ... | ... |
yudao-ui-admin-vue3/src/components/Setting/src/components/InterfaceDisplay.vue
| 1 | 1 | <script setup lang="ts"> |
| 2 | -import { ElSwitch } from 'element-plus' | |
| 2 | +import { ElSwitch, ElMessage } from 'element-plus' | |
| 3 | 3 | import { useI18n } from '@/hooks/web/useI18n' |
| 4 | 4 | import { useAppStore } from '@/store/modules/app' |
| 5 | 5 | import { computed, ref, watch } from 'vue' |
| ... | ... | @@ -107,6 +107,21 @@ const greyModeChange = (show: boolean) => { |
| 107 | 107 | appStore.setGreyMode(show) |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | +// 动态路由 | |
| 111 | +const dynamicRouter = ref(appStore.getDynamicRouter) | |
| 112 | + | |
| 113 | +const dynamicRouterChange = (show: boolean) => { | |
| 114 | + ElMessage.info(t('setting.reExperienced')) | |
| 115 | + appStore.setDynamicRouter(show) | |
| 116 | +} | |
| 117 | + | |
| 118 | +// 固定菜单 | |
| 119 | +const fixedMenu = ref(appStore.getFixedMenu) | |
| 120 | + | |
| 121 | +const fixedMenuChange = (show: boolean) => { | |
| 122 | + appStore.setFixedMenu(show) | |
| 123 | +} | |
| 124 | + | |
| 110 | 125 | const layout = computed(() => appStore.getLayout) |
| 111 | 126 | |
| 112 | 127 | watch( |
| ... | ... | @@ -185,5 +200,15 @@ watch( |
| 185 | 200 | <span class="text-14px">{{ t('setting.greyMode') }}</span> |
| 186 | 201 | <ElSwitch v-model="greyMode" @change="greyModeChange" /> |
| 187 | 202 | </div> |
| 203 | + | |
| 204 | + <div class="flex justify-between items-center"> | |
| 205 | + <span class="text-14px">{{ t('setting.dynamicRouter') }}</span> | |
| 206 | + <ElSwitch v-model="dynamicRouter" @change="dynamicRouterChange" /> | |
| 207 | + </div> | |
| 208 | + | |
| 209 | + <div class="flex justify-between items-center"> | |
| 210 | + <span class="text-14px">{{ t('setting.fixedMenu') }}</span> | |
| 211 | + <ElSwitch v-model="fixedMenu" @change="fixedMenuChange" /> | |
| 212 | + </div> | |
| 188 | 213 | </div> |
| 189 | 214 | </template> | ... | ... |
yudao-ui-admin-vue3/src/components/SizeDropdown/src/SizeDropdown.vue
| ... | ... | @@ -5,6 +5,7 @@ import { useAppStore } from '@/store/modules/app' |
| 5 | 5 | import { useI18n } from '@/hooks/web/useI18n' |
| 6 | 6 | import { propTypes } from '@/utils/propTypes' |
| 7 | 7 | import { useDesign } from '@/hooks/web/useDesign' |
| 8 | +import { ElementPlusSize } from '@/types/elementPlus' | |
| 8 | 9 | |
| 9 | 10 | const { getPrefixCls } = useDesign() |
| 10 | 11 | |
| ... | ... | @@ -20,7 +21,7 @@ const appStore = useAppStore() |
| 20 | 21 | |
| 21 | 22 | const sizeMap = computed(() => appStore.sizeMap) |
| 22 | 23 | |
| 23 | -const setCurrentSize = (size: ElememtPlusSize) => { | |
| 24 | +const setCurrentSize = (size: ElementPlusSize) => { | |
| 24 | 25 | appStore.setCurrentSize(size) |
| 25 | 26 | } |
| 26 | 27 | </script> | ... | ... |
yudao-ui-admin-vue3/src/components/TabMenu/src/TabMenu.vue
| 1 | 1 | <script lang="tsx"> |
| 2 | 2 | import { usePermissionStore } from '@/store/modules/permission' |
| 3 | 3 | import { useAppStore } from '@/store/modules/app' |
| 4 | -import { computed, unref, defineComponent, watch, ref } from 'vue' | |
| 4 | +import { computed, unref, defineComponent, watch, ref, onMounted } from 'vue' | |
| 5 | 5 | import { useI18n } from '@/hooks/web/useI18n' |
| 6 | 6 | import { ElScrollbar } from 'element-plus' |
| 7 | 7 | import { Icon } from '@/components/Icon' |
| ... | ... | @@ -28,6 +28,8 @@ export default defineComponent({ |
| 28 | 28 | |
| 29 | 29 | const collapse = computed(() => appStore.getCollapse) |
| 30 | 30 | |
| 31 | + const fixedMenu = computed(() => appStore.getFixedMenu) | |
| 32 | + | |
| 31 | 33 | const permissionStore = usePermissionStore() |
| 32 | 34 | |
| 33 | 35 | const routers = computed(() => permissionStore.getRouters) |
| ... | ... | @@ -38,6 +40,27 @@ export default defineComponent({ |
| 38 | 40 | appStore.setCollapse(!unref(collapse)) |
| 39 | 41 | } |
| 40 | 42 | |
| 43 | + onMounted(() => { | |
| 44 | + if (unref(fixedMenu)) { | |
| 45 | + const path = `/${unref(currentRoute).path.split('/')[1]}` | |
| 46 | + const children = unref(tabRouters).find( | |
| 47 | + (v) => | |
| 48 | + (v.meta?.alwaysShow || (v?.children?.length && v?.children?.length > 1)) && | |
| 49 | + v.path === path | |
| 50 | + )?.children | |
| 51 | + | |
| 52 | + tabActive.value = path | |
| 53 | + if (children) { | |
| 54 | + permissionStore.setMenuTabRouters( | |
| 55 | + cloneDeep(children).map((v) => { | |
| 56 | + v.path = pathResolve(unref(tabActive), v.path) | |
| 57 | + return v | |
| 58 | + }) | |
| 59 | + ) | |
| 60 | + } | |
| 61 | + } | |
| 62 | + }) | |
| 63 | + | |
| 41 | 64 | watch( |
| 42 | 65 | () => routers.value, |
| 43 | 66 | (routers: AppRouteRecordRaw[]) => { |
| ... | ... | @@ -55,6 +78,9 @@ export default defineComponent({ |
| 55 | 78 | watch( |
| 56 | 79 | () => collapse.value, |
| 57 | 80 | (collapse: boolean) => { |
| 81 | + if (unref(fixedMenu)) { | |
| 82 | + return | |
| 83 | + } | |
| 58 | 84 | if (!collapse) { |
| 59 | 85 | setTimeout(() => { |
| 60 | 86 | showTitle.value = !collapse |
| ... | ... | @@ -66,7 +92,7 @@ export default defineComponent({ |
| 66 | 92 | ) |
| 67 | 93 | |
| 68 | 94 | // 是否显示菜单 |
| 69 | - const showMenu = ref(false) | |
| 95 | + const showMenu = ref(unref(fixedMenu) ? true : false) | |
| 70 | 96 | |
| 71 | 97 | // tab高亮 |
| 72 | 98 | const tabActive = ref('') |
| ... | ... | @@ -77,9 +103,13 @@ export default defineComponent({ |
| 77 | 103 | window.open(item.path) |
| 78 | 104 | return |
| 79 | 105 | } |
| 106 | + const newPath = item.children ? item.path : item.path.split('/')[0] | |
| 107 | + const oldPath = unref(tabActive) | |
| 80 | 108 | tabActive.value = item.children ? item.path : item.path.split('/')[0] |
| 81 | 109 | if (item.children) { |
| 82 | - showMenu.value = !unref(showMenu) | |
| 110 | + if (newPath === oldPath || !unref(showMenu)) { | |
| 111 | + showMenu.value = unref(fixedMenu) ? true : !unref(showMenu) | |
| 112 | + } | |
| 83 | 113 | if (unref(showMenu)) { |
| 84 | 114 | permissionStore.setMenuTabRouters( |
| 85 | 115 | cloneDeep(item.children).map((v) => { |
| ... | ... | @@ -96,7 +126,7 @@ export default defineComponent({ |
| 96 | 126 | } |
| 97 | 127 | |
| 98 | 128 | // 设置高亮 |
| 99 | - const isActice = (currentPath: string) => { | |
| 129 | + const isActive = (currentPath: string) => { | |
| 100 | 130 | const { path } = unref(currentRoute) |
| 101 | 131 | if (tabPathMap[currentPath].includes(path)) { |
| 102 | 132 | return true |
| ... | ... | @@ -105,7 +135,7 @@ export default defineComponent({ |
| 105 | 135 | } |
| 106 | 136 | |
| 107 | 137 | const mouseleave = () => { |
| 108 | - if (!unref(showMenu)) return | |
| 138 | + if (!unref(showMenu) || unref(fixedMenu)) return | |
| 109 | 139 | showMenu.value = false |
| 110 | 140 | } |
| 111 | 141 | |
| ... | ... | @@ -114,7 +144,7 @@ export default defineComponent({ |
| 114 | 144 | id={`${variables.namespace}-menu`} |
| 115 | 145 | class={[ |
| 116 | 146 | prefixCls, |
| 117 | - 'relative bg-[var(--left-menu-bg-color)] top-1px z-999', | |
| 147 | + 'relative bg-[var(--left-menu-bg-color)] top-1px z-99999', | |
| 118 | 148 | { |
| 119 | 149 | 'w-[var(--tab-menu-max-width)]': !unref(collapse), |
| 120 | 150 | 'w-[var(--tab-menu-min-width)]': unref(collapse) |
| ... | ... | @@ -140,7 +170,7 @@ export default defineComponent({ |
| 140 | 170 | `${prefixCls}__item`, |
| 141 | 171 | 'text-center text-12px relative py-12px cursor-pointer', |
| 142 | 172 | { |
| 143 | - 'is-active': isActice(v.path) | |
| 173 | + 'is-active': isActive(v.path) | |
| 144 | 174 | } |
| 145 | 175 | ]} |
| 146 | 176 | onClick={() => { |
| ... | ... | @@ -174,8 +204,8 @@ export default defineComponent({ |
| 174 | 204 | { |
| 175 | 205 | '!left-[var(--tab-menu-min-width)]': unref(collapse), |
| 176 | 206 | '!left-[var(--tab-menu-max-width)]': !unref(collapse), |
| 177 | - '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu), | |
| 178 | - '!w-0': !unref(showMenu) | |
| 207 | + '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu) || unref(fixedMenu), | |
| 208 | + '!w-0': !unref(showMenu) && !unref(fixedMenu) | |
| 179 | 209 | } |
| 180 | 210 | ]} |
| 181 | 211 | style="transition: width var(--transition-time-02), left var(--transition-time-02);" | ... | ... |
yudao-ui-admin-vue3/src/components/TabMenu/src/helper.ts
| ... | ... | @@ -28,9 +28,9 @@ export const filterMenusPath = ( |
| 28 | 28 | let data: Nullable<AppRouteRecordRaw> = null |
| 29 | 29 | const meta = (v.meta ?? {}) as RouteMeta |
| 30 | 30 | if (!meta.hidden || meta.canTo) { |
| 31 | - const allParentPaht = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path) | |
| 31 | + const allParentPath = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path) | |
| 32 | 32 | |
| 33 | - const fullPath = isUrl(v.path) ? v.path : allParentPaht.join('/') | |
| 33 | + const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/') | |
| 34 | 34 | |
| 35 | 35 | data = cloneDeep(v) |
| 36 | 36 | data.path = fullPath |
| ... | ... | @@ -42,8 +42,8 @@ export const filterMenusPath = ( |
| 42 | 42 | res.push(data) |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | - if (allParentPaht.length && Reflect.has(tabPathMap, allParentPaht[0])) { | |
| 46 | - tabPathMap[allParentPaht[0]].push(fullPath) | |
| 45 | + if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) { | |
| 46 | + tabPathMap[allParentPath[0]].push(fullPath) | |
| 47 | 47 | } |
| 48 | 48 | } |
| 49 | 49 | } | ... | ... |
yudao-ui-admin-vue3/src/components/Table/index.ts
| 1 | 1 | import Table from './src/Table.vue' |
| 2 | +import { ElTable } from 'element-plus' | |
| 3 | +import { TableSetPropsType } from '@/types/table' | |
| 2 | 4 | |
| 3 | 5 | export interface TableExpose { |
| 4 | 6 | setProps: (props: Recordable) => void |
| 5 | 7 | setColumn: (columnProps: TableSetPropsType[]) => void |
| 6 | 8 | selections: Recordable[] |
| 9 | + elTableRef: ComponentRef<typeof ElTable> | |
| 7 | 10 | } |
| 8 | 11 | |
| 9 | 12 | export { Table } | ... | ... |
yudao-ui-admin-vue3/src/components/Table/src/types.ts
yudao-ui-admin-vue3/src/hooks/web/useConfigGlobal.ts
yudao-ui-admin-vue3/src/hooks/web/useCrudSchemas.ts
| 1 | 1 | import { reactive } from 'vue' |
| 2 | 2 | import { eachTree, treeMap, filter } from '@/utils/tree' |
| 3 | 3 | import { getIntDictOptions } from '@/utils/dict' |
| 4 | +import { FormSchema } from '@/types/form' | |
| 5 | +import { TableColumn } from '@/types/table' | |
| 6 | +import { DescriptionsSchema } from '@/types/descriptions' | |
| 4 | 7 | |
| 5 | 8 | export type CrudSchema = Omit<TableColumn, 'children'> & { |
| 6 | 9 | search?: CrudSearchParams | ... | ... |
yudao-ui-admin-vue3/src/hooks/web/useForm.ts
| ... | ... | @@ -2,6 +2,7 @@ import type { Form, FormExpose } from '@/components/Form' |
| 2 | 2 | import type { ElForm } from 'element-plus' |
| 3 | 3 | import { ref, unref, nextTick } from 'vue' |
| 4 | 4 | import type { FormProps } from '@/components/Form/src/types' |
| 5 | +import { FormSchema, FormSetPropsType } from '@/types/form' | |
| 5 | 6 | |
| 6 | 7 | export const useForm = (props?: FormProps) => { |
| 7 | 8 | // From实例 | ... | ... |
yudao-ui-admin-vue3/src/hooks/web/useIcon.ts
yudao-ui-admin-vue3/src/hooks/web/useTable.ts
| ... | ... | @@ -4,6 +4,7 @@ import { ElMessage, ElMessageBox, ElTable } from 'element-plus' |
| 4 | 4 | import { computed, nextTick, reactive, ref, unref, watch } from 'vue' |
| 5 | 5 | import type { TableProps } from '@/components/Table/src/types' |
| 6 | 6 | import { useI18n } from '@/hooks/web/useI18n' |
| 7 | +import { TableSetPropsType } from '@/types/table' | |
| 7 | 8 | |
| 8 | 9 | const { t } = useI18n() |
| 9 | 10 | interface ResponseType<T = any> { |
| ... | ... | @@ -150,13 +151,17 @@ export const useTable = <T = any>(config?: UseTableConfig<T>) => { |
| 150 | 151 | }, |
| 151 | 152 | // 与Search组件结合 |
| 152 | 153 | setSearchParams: (data: Recordable) => { |
| 153 | - tableObject.currentPage = 1 | |
| 154 | 154 | tableObject.params = Object.assign(tableObject.params, { |
| 155 | 155 | pageSize: tableObject.pageSize, |
| 156 | - pageNo: tableObject.currentPage, | |
| 156 | + pageNo: 1, | |
| 157 | 157 | ...data |
| 158 | 158 | }) |
| 159 | - methods.getList() | |
| 159 | + // 页码不等于1时更新页码重新获取数据,页码等于1时重新获取数据 | |
| 160 | + if (tableObject.currentPage !== 1) { | |
| 161 | + tableObject.currentPage = 1 | |
| 162 | + } else { | |
| 163 | + methods.getList() | |
| 164 | + } | |
| 160 | 165 | }, |
| 161 | 166 | // 删除数据 |
| 162 | 167 | delList: async ( | ... | ... |
yudao-ui-admin-vue3/src/layout/components/useRenderLayout.tsx
| ... | ... | @@ -32,6 +32,9 @@ const fixedHeader = computed(() => appStore.getFixedHeader) |
| 32 | 32 | // 是否是移动端 |
| 33 | 33 | const mobile = computed(() => appStore.getMobile) |
| 34 | 34 | |
| 35 | +// 固定菜单 | |
| 36 | +const fixedMenu = computed(() => appStore.getFixedMenu) | |
| 37 | + | |
| 35 | 38 | export const useRenderLayout = () => { |
| 36 | 39 | const renderClassic = () => { |
| 37 | 40 | return ( |
| ... | ... | @@ -213,9 +216,13 @@ export const useRenderLayout = () => { |
| 213 | 216 | 'h-[100%]', |
| 214 | 217 | { |
| 215 | 218 | 'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]': |
| 216 | - collapse.value, | |
| 219 | + collapse.value && !fixedMenu.value, | |
| 217 | 220 | 'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)]': |
| 218 | - !collapse.value | |
| 221 | + !collapse.value && !fixedMenu.value, | |
| 222 | + 'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]': | |
| 223 | + collapse.value && fixedMenu.value, | |
| 224 | + 'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]': | |
| 225 | + !collapse.value && fixedMenu.value | |
| 219 | 226 | } |
| 220 | 227 | ]} |
| 221 | 228 | style="transition: all var(--transition-time-02);" |
| ... | ... | @@ -239,7 +246,13 @@ export const useRenderLayout = () => { |
| 239 | 246 | 'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]': |
| 240 | 247 | collapse.value && fixedHeader.value, |
| 241 | 248 | 'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]': |
| 242 | - !collapse.value && fixedHeader.value | |
| 249 | + !collapse.value && fixedHeader.value, | |
| 250 | + '!fixed top-0 left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10': | |
| 251 | + fixedHeader.value && fixedMenu.value, | |
| 252 | + '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)]': | |
| 253 | + collapse.value && fixedHeader.value && fixedMenu.value, | |
| 254 | + '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)]': | |
| 255 | + !collapse.value && fixedHeader.value && fixedMenu.value | |
| 243 | 256 | } |
| 244 | 257 | ]} |
| 245 | 258 | style="transition: width var(--transition-time-02), left var(--transition-time-02);" | ... | ... |
yudao-ui-admin-vue3/src/locales/en.ts
| ... | ... | @@ -91,7 +91,10 @@ export default { |
| 91 | 91 | copyFailed: 'Copy failed', |
| 92 | 92 | footer: 'Footer', |
| 93 | 93 | uniqueOpened: 'Unique opened', |
| 94 | - tagsViewIcon: 'Tags view icon' | |
| 94 | + tagsViewIcon: 'Tags view icon', | |
| 95 | + dynamicRouter: 'Dynamic router', | |
| 96 | + reExperienced: 'Please exit the login experience again', | |
| 97 | + fixedMenu: 'Fixed menu' | |
| 95 | 98 | }, |
| 96 | 99 | size: { |
| 97 | 100 | default: 'Default', | ... | ... |
yudao-ui-admin-vue3/src/locales/zh-CN.ts
| ... | ... | @@ -91,7 +91,10 @@ export default { |
| 91 | 91 | copyFailed: '拷贝失败', |
| 92 | 92 | footer: '页脚', |
| 93 | 93 | uniqueOpened: '菜单手风琴', |
| 94 | - tagsViewIcon: '标签页图标' | |
| 94 | + tagsViewIcon: '标签页图标', | |
| 95 | + dynamicRouter: '动态路由', | |
| 96 | + reExperienced: '请重新退出登录体验', | |
| 97 | + fixedMenu: '固定菜单' | |
| 95 | 98 | }, |
| 96 | 99 | size: { |
| 97 | 100 | default: '默认', | ... | ... |
yudao-ui-admin-vue3/src/store/modules/app.ts
| ... | ... | @@ -3,27 +3,12 @@ import { store } from '../index' |
| 3 | 3 | import { setCssVar, humpToUnderline } from '@/utils' |
| 4 | 4 | import { ElMessage } from 'element-plus' |
| 5 | 5 | import { useCache } from '@/hooks/web/useCache' |
| 6 | +import { ElementPlusSize } from '@/types/elementPlus' | |
| 7 | +import { LayoutType } from '@/types/layout' | |
| 8 | +import { ThemeTypes } from '@/types/theme' | |
| 6 | 9 | |
| 7 | 10 | const { wsCache } = useCache() |
| 8 | 11 | |
| 9 | -type LayoutType = 'classic' | 'topLeft' | 'top' | 'cutMenu' | |
| 10 | - | |
| 11 | -type ThemeTypes = { | |
| 12 | - elColorPrimary?: string | |
| 13 | - leftMenuBorderColor?: string | |
| 14 | - leftMenuBgColor?: string | |
| 15 | - leftMenuBgLightColor?: string | |
| 16 | - leftMenuBgActiveColor?: string | |
| 17 | - leftMenuCollapseBgActiveColor?: string | |
| 18 | - leftMenuTextColor?: string | |
| 19 | - leftMenuTextActiveColor?: string | |
| 20 | - logoTitleTextColor?: string | |
| 21 | - logoBorderColor?: string | |
| 22 | - topHeaderBgColor?: string | |
| 23 | - topHeaderTextColor?: string | |
| 24 | - topHeaderHoverColor?: string | |
| 25 | - topToolBorderColor?: string | |
| 26 | -} | |
| 27 | 12 | interface AppState { |
| 28 | 13 | breadcrumb: boolean |
| 29 | 14 | breadcrumbIcon: boolean |
| ... | ... | @@ -43,11 +28,12 @@ interface AppState { |
| 43 | 28 | title: string |
| 44 | 29 | userInfo: string |
| 45 | 30 | isDark: boolean |
| 46 | - currentSize: ElememtPlusSize | |
| 47 | - sizeMap: ElememtPlusSize[] | |
| 31 | + currentSize: ElementPlusSize | |
| 32 | + sizeMap: ElementPlusSize[] | |
| 48 | 33 | mobile: boolean |
| 49 | 34 | footer: boolean |
| 50 | 35 | theme: ThemeTypes |
| 36 | + fixedMenu: boolean | |
| 51 | 37 | } |
| 52 | 38 | |
| 53 | 39 | export const useAppStore = defineStore('app', { |
| ... | ... | @@ -73,6 +59,7 @@ export const useAppStore = defineStore('app', { |
| 73 | 59 | fixedHeader: true, // 固定toolheader |
| 74 | 60 | footer: true, // 显示页脚 |
| 75 | 61 | greyMode: false, // 是否开始灰色模式,用于特殊悼念日 |
| 62 | + fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单 | |
| 76 | 63 | |
| 77 | 64 | layout: wsCache.get('layout') || 'classic', // layout布局 |
| 78 | 65 | isDark: wsCache.get('isDark') || false, // 是否是暗黑模式 |
| ... | ... | @@ -149,6 +136,9 @@ export const useAppStore = defineStore('app', { |
| 149 | 136 | getGreyMode(): boolean { |
| 150 | 137 | return this.greyMode |
| 151 | 138 | }, |
| 139 | + getFixedMenu(): boolean { | |
| 140 | + return this.fixedMenu | |
| 141 | + }, | |
| 152 | 142 | getPageLoading(): boolean { |
| 153 | 143 | return this.pageLoading |
| 154 | 144 | }, |
| ... | ... | @@ -164,10 +154,10 @@ export const useAppStore = defineStore('app', { |
| 164 | 154 | getIsDark(): boolean { |
| 165 | 155 | return this.isDark |
| 166 | 156 | }, |
| 167 | - getCurrentSize(): ElememtPlusSize { | |
| 157 | + getCurrentSize(): ElementPlusSize { | |
| 168 | 158 | return this.currentSize |
| 169 | 159 | }, |
| 170 | - getSizeMap(): ElememtPlusSize[] { | |
| 160 | + getSizeMap(): ElementPlusSize[] { | |
| 171 | 161 | return this.sizeMap |
| 172 | 162 | }, |
| 173 | 163 | getMobile(): boolean { |
| ... | ... | @@ -220,6 +210,10 @@ export const useAppStore = defineStore('app', { |
| 220 | 210 | setGreyMode(greyMode: boolean) { |
| 221 | 211 | this.greyMode = greyMode |
| 222 | 212 | }, |
| 213 | + setFixedMenu(fixedMenu: boolean) { | |
| 214 | + wsCache.set('fixedMenu', fixedMenu) | |
| 215 | + this.fixedMenu = fixedMenu | |
| 216 | + }, | |
| 223 | 217 | setPageLoading(pageLoading: boolean) { |
| 224 | 218 | this.pageLoading = pageLoading |
| 225 | 219 | }, |
| ... | ... | @@ -245,7 +239,7 @@ export const useAppStore = defineStore('app', { |
| 245 | 239 | } |
| 246 | 240 | wsCache.set('isDark', this.isDark) |
| 247 | 241 | }, |
| 248 | - setCurrentSize(currentSize: ElememtPlusSize) { | |
| 242 | + setCurrentSize(currentSize: ElementPlusSize) { | |
| 249 | 243 | this.currentSize = currentSize |
| 250 | 244 | wsCache.set('currentSize', this.currentSize) |
| 251 | 245 | }, | ... | ... |
yudao-ui-admin-vue3/src/store/modules/locale.ts
| ... | ... | @@ -3,6 +3,7 @@ import { store } from '../index' |
| 3 | 3 | import zhCn from 'element-plus/es/locale/lang/zh-cn' |
| 4 | 4 | import en from 'element-plus/es/locale/lang/en' |
| 5 | 5 | import { useCache } from '@/hooks/web/useCache' |
| 6 | +import { LocaleDropdownType } from '@/types/localeDropdown' | |
| 6 | 7 | |
| 7 | 8 | const { wsCache } = useCache() |
| 8 | 9 | ... | ... |
yudao-ui-admin-vue3/types/componentType/configGlobal.d.ts deleted
yudao-ui-admin-vue3/types/componentType/contextMenu.d.ts deleted
yudao-ui-admin-vue3/types/componentType/descriptions.d.ts deleted
| 1 | -declare interface DescriptionsSchema { | |
| 2 | - span?: number // 占多少分 | |
| 3 | - field: string // 字段名 | |
| 4 | - label?: string // label名 | |
| 5 | - width?: string | number | |
| 6 | - minWidth?: string | number | |
| 7 | - align?: 'left' | 'center' | 'right' | |
| 8 | - labelAlign?: 'left' | 'center' | 'right' | |
| 9 | - className?: string | |
| 10 | - labelClassName?: string | |
| 11 | -} |
yudao-ui-admin-vue3/types/componentType/form.d.ts deleted
| 1 | -import type { CSSProperties } from 'vue' | |
| 2 | - | |
| 3 | -declare global { | |
| 4 | - declare type ComponentName = | |
| 5 | - | 'Radio' | |
| 6 | - | 'RadioButton' | |
| 7 | - | 'Checkbox' | |
| 8 | - | 'CheckboxButton' | |
| 9 | - | 'Input' | |
| 10 | - | 'Autocomplete' | |
| 11 | - | 'InputNumber' | |
| 12 | - | 'Select' | |
| 13 | - | 'Cascader' | |
| 14 | - | 'Switch' | |
| 15 | - | 'Slider' | |
| 16 | - | 'TimePicker' | |
| 17 | - | 'DatePicker' | |
| 18 | - | 'Rate' | |
| 19 | - | 'ColorPicker' | |
| 20 | - | 'Transfer' | |
| 21 | - | 'Divider' | |
| 22 | - | 'TimeSelect' | |
| 23 | - | 'SelectV2' | |
| 24 | - | 'InputPassword' | |
| 25 | - | 'Editor' | |
| 26 | - | |
| 27 | - declare type ColProps = { | |
| 28 | - span?: number | |
| 29 | - xs?: number | |
| 30 | - sm?: number | |
| 31 | - md?: number | |
| 32 | - lg?: number | |
| 33 | - xl?: number | |
| 34 | - tag?: string | |
| 35 | - } | |
| 36 | - | |
| 37 | - declare type FormValueType = string | number | string[] | number[] | boolean | undefined | null | |
| 38 | - | |
| 39 | - declare type FormItemProps = { | |
| 40 | - labelWidth?: string | number | |
| 41 | - required?: boolean | |
| 42 | - rules?: Recordable | |
| 43 | - error?: string | |
| 44 | - showMessage?: boolean | |
| 45 | - inlineMessage?: boolean | |
| 46 | - style?: CSSProperties | |
| 47 | - } | |
| 48 | - | |
| 49 | - declare type ComponentOptions = { | |
| 50 | - label?: string | |
| 51 | - value?: FormValueType | |
| 52 | - disabled?: boolean | |
| 53 | - key?: string | number | |
| 54 | - children?: ComponentOptions[] | |
| 55 | - options?: ComponentOptions[] | |
| 56 | - } & Recordable | |
| 57 | - | |
| 58 | - declare type ComponentOptionsAlias = { | |
| 59 | - labelField?: string | |
| 60 | - valueField?: string | |
| 61 | - } | |
| 62 | - | |
| 63 | - declare type ComponentProps = { | |
| 64 | - optionsAlias?: ComponentOptionsAlias | |
| 65 | - options?: ComponentOptions[] | |
| 66 | - optionsSlot?: boolean | |
| 67 | - } & Recordable | |
| 68 | - | |
| 69 | - declare type FormSchema = { | |
| 70 | - // 唯一值 | |
| 71 | - field: string | |
| 72 | - // 标题 | |
| 73 | - label?: string | |
| 74 | - // 提示 | |
| 75 | - labelMessage?: string | |
| 76 | - // col组件属性 | |
| 77 | - colProps?: ColProps | |
| 78 | - // 表单组件属性,slots对应的是表单组件的插槽,规则:${field}-xxx,具体可以查看element-plus文档 | |
| 79 | - componentProps?: { slots?: Recordable } & ComponentProps | |
| 80 | - // formItem组件属性 | |
| 81 | - formItemProps?: FormItemProps | |
| 82 | - // 渲染的组件 | |
| 83 | - component?: ComponentName | |
| 84 | - // 初始值 | |
| 85 | - value?: FormValueType | |
| 86 | - // 是否隐藏 | |
| 87 | - hidden?: boolean | |
| 88 | - // 远程加载下拉项 | |
| 89 | - api?: <T = any>() => Promise<T> | |
| 90 | - } | |
| 91 | - | |
| 92 | - declare type FormSetPropsType = { | |
| 93 | - field: string | |
| 94 | - path: string | |
| 95 | - value: any | |
| 96 | - } | |
| 97 | -} |
yudao-ui-admin-vue3/types/componentType/icon.d.ts deleted
yudao-ui-admin-vue3/types/componentType/infotip.d.ts deleted
yudao-ui-admin-vue3/types/componentType/localeDropdown.d.ts deleted
yudao-ui-admin-vue3/types/componentType/qrcode.d.ts deleted
yudao-ui-admin-vue3/types/componentType/table.d.ts deleted
| 1 | -declare type TableColumn = { | |
| 2 | - field: string | |
| 3 | - label?: string | |
| 4 | - children?: TableColumn[] | |
| 5 | -} & Recordable | |
| 6 | - | |
| 7 | -declare type TableSlotDefault = { | |
| 8 | - row: Recordable | |
| 9 | - column: TableColumn | |
| 10 | - $index: number | |
| 11 | -} & Recordable | |
| 12 | - | |
| 13 | -declare interface Pagination { | |
| 14 | - small?: boolean | |
| 15 | - background?: boolean | |
| 16 | - pageSize?: number | |
| 17 | - defaultPageSize?: number | |
| 18 | - total?: number | |
| 19 | - pageCount?: number | |
| 20 | - pagerCount?: number | |
| 21 | - currentPage?: number | |
| 22 | - defaultCurrentPage?: number | |
| 23 | - layout?: string | |
| 24 | - pageSizes?: number[] | |
| 25 | - popperClass?: string | |
| 26 | - prevText?: string | |
| 27 | - nextText?: string | |
| 28 | - disabled?: boolean | |
| 29 | - hideOnSinglePage?: boolean | |
| 30 | -} | |
| 31 | - | |
| 32 | -declare interface TableSetPropsType { | |
| 33 | - field: string | |
| 34 | - path: string | |
| 35 | - value: any | |
| 36 | -} |
yudao-ui-admin-vue3/types/global.d.ts
| 1 | -declare interface Fn<T = any> { | |
| 2 | - (...arg: T[]): T | |
| 3 | -} | |
| 4 | - | |
| 5 | -declare type Nullable<T> = T | null | |
| 1 | +import type { CSSProperties } from 'vue' | |
| 2 | +declare global { | |
| 3 | + declare interface Fn<T = any> { | |
| 4 | + (...arg: T[]): T | |
| 5 | + } | |
| 6 | 6 | |
| 7 | -declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T> | |
| 7 | + declare type Nullable<T> = T | null | |
| 8 | 8 | |
| 9 | -declare type ElememtPlusSize = 'default' | 'small' | 'large' | |
| 9 | + declare type ElRef<T extends HTMLElement = HTMLDivElement> = Nullable<T> | |
| 10 | 10 | |
| 11 | -declare type ElementPlusInfoType = 'success' | 'info' | 'warning' | 'danger' | |
| 11 | + declare type Recordable<T = any, K = string> = Record<K extends null | undefined ? string : K, T> | |
| 12 | 12 | |
| 13 | -declare type Recordable<T = any, K = string> = Record<K extends null | undefined ? string : K, T> | |
| 13 | + declare type ComponentRef<T> = InstanceType<T> | |
| 14 | 14 | |
| 15 | -declare type ComponentRef<T> = InstanceType<T> | |
| 15 | + declare type LocaleType = 'zh-CN' | 'en' | |
| 16 | 16 | |
| 17 | -declare type LocaleType = 'zh-CN' | 'en' | |
| 17 | + declare type AxiosHeaders = | |
| 18 | + | 'application/json' | |
| 19 | + | 'application/x-www-form-urlencoded' | |
| 20 | + | 'multipart/form-data' | |
| 18 | 21 | |
| 19 | -declare type AxiosHeaders = | |
| 20 | - | 'application/json' | |
| 21 | - | 'application/x-www-form-urlencoded' | |
| 22 | - | 'multipart/form-data' | |
| 22 | + declare type AxiosMethod = 'get' | 'post' | 'delete' | 'put' | |
| 23 | 23 | |
| 24 | -declare type AxiosMethod = 'GET' | 'POST' | 'DELETE' | 'PUT' | |
| 24 | + declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | |
| 25 | 25 | |
| 26 | -declare type AxiosResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | |
| 27 | - | |
| 28 | -declare interface AxiosConfig { | |
| 29 | - params?: any | |
| 30 | - data?: any | |
| 31 | - url?: string | |
| 32 | - method?: AxiosMethod | |
| 33 | - headersType?: string | |
| 34 | - responseType?: AxiosResponseType | |
| 35 | -} | |
| 26 | + declare interface AxiosConfig { | |
| 27 | + params?: any | |
| 28 | + data?: any | |
| 29 | + url?: string | |
| 30 | + method?: AxiosMethod | |
| 31 | + headersType?: string | |
| 32 | + responseType?: AxiosResponseType | |
| 33 | + } | |
| 36 | 34 | |
| 37 | -declare interface IResponse<T = any> { | |
| 38 | - code?: number | |
| 39 | - data: T extends any ? T : T & any | |
| 35 | + declare interface IResponse<T = any> { | |
| 36 | + code: string | |
| 37 | + data: T extends any ? T : T & any | |
| 38 | + } | |
| 40 | 39 | } | ... | ... |