| @@ -24,7 +24,8 @@ const tagsViewStore = useTagsViewStore(); | |||
| /* 50= navbar 50 */ | |||
| min-height: calc(100vh - 50px); | |||
| overflow: hidden; | |||
| background-color: var(--el-bg-color-page); | |||
| // background-color: var(--el-bg-color-page); | |||
| background-color: #000; | |||
| } | |||
| .fixed-header + .app-main { | |||
| @@ -1,4 +1,5 @@ | |||
| <script setup lang="ts"> | |||
| import { watch, ref } from "vue"; | |||
| import { storeToRefs } from "pinia"; | |||
| import { RouteLocationRaw, useRoute, useRouter } from "vue-router"; | |||
| import { useAppStore } from "@/store/modules/app"; | |||
| @@ -49,41 +50,53 @@ function logout() { | |||
| function routerTo() { | |||
| router.push("/myAccount"); | |||
| } | |||
| // 当前路由的名字 | |||
| const routeName = ref(route.meta.name); | |||
| watch( | |||
| () => route.meta.name, | |||
| (newName) => { | |||
| routeName.value = newName; | |||
| } | |||
| ); | |||
| </script> | |||
| <template> | |||
| <!-- 顶部导航栏 --> | |||
| <div class="navbar"> | |||
| <div class="myNavbar"> | |||
| <!-- 左侧面包屑 --> | |||
| <div class="flex"> | |||
| <div class="flex" v-if="false"> | |||
| <hamburger | |||
| :is-active="appStore.sidebar.opened" | |||
| @toggleClick="toggleSideBar" | |||
| /> | |||
| <breadcrumb /> | |||
| </div> | |||
| <!-- 右侧导航设置 --> | |||
| <div class="flex"> | |||
| <div class="flex" v-if="false"> | |||
| <!-- 导航栏设置(窄屏隐藏)--> | |||
| <div class="setting-container" v-if="device !== 'mobile'"> | |||
| <!--全屏 --> | |||
| <div class="setting-item" @click="toggle"> | |||
| <div class="setting-item" @click="toggle" v-if="false"> | |||
| <svg-icon | |||
| :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" | |||
| /> | |||
| </div> | |||
| <!-- 布局大小 --> | |||
| <el-tooltip content="布局大小" effect="dark" placement="bottom"> | |||
| <el-tooltip | |||
| content="布局大小" | |||
| effect="dark" | |||
| placement="bottom" | |||
| v-if="false" | |||
| > | |||
| <size-select class="setting-item" /> | |||
| </el-tooltip> | |||
| <!--语言选择--> | |||
| <lang-select class="setting-item" /> | |||
| <lang-select class="setting-item" v-if="false" /> | |||
| </div> | |||
| <!-- 用户头像 --> | |||
| <span @click="routerTo">个人账户</span> | |||
| <el-dropdown trigger="click"> | |||
| <el-dropdown trigger="click" v-if="false"> | |||
| <div class="avatar-container"> | |||
| <img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" /> | |||
| <i-ep-caret-bottom class="w-3 h-3" /> | |||
| @@ -109,6 +122,11 @@ function routerTo() { | |||
| </template> | |||
| </el-dropdown> | |||
| </div> | |||
| <!-- 显示的,以上代码作废 --> | |||
| <div style="position: absolute; left: 30px">{{ routeName }}</div> | |||
| <div class="avatar"></div> | |||
| <div @click="routerTo">个人账户</div> | |||
| <div @click="logout" style="margin-left: 10px">退出登录</div> | |||
| </div> | |||
| </template> | |||
| @@ -154,4 +172,24 @@ function routerTo() { | |||
| } | |||
| } | |||
| } | |||
| // 代替原来的navbar | |||
| .myNavbar { | |||
| display: flex; | |||
| align-items: center; | |||
| justify-content: flex-end; | |||
| height: 50px; | |||
| padding: 0 20px; | |||
| color: #fff; | |||
| background-color: #fff; | |||
| background-color: #000; | |||
| box-shadow: 0 0 1px #0003; | |||
| .avatar { | |||
| width: 30px; | |||
| height: 30px; | |||
| margin-right: 5px; | |||
| background-color: red; | |||
| border-radius: 50%; | |||
| } | |||
| } | |||
| </style> | |||
| @@ -1,13 +1,13 @@ | |||
| <script lang="ts" setup> | |||
| import { useSettingsStore } from '@/store/modules/settings'; | |||
| import { useSettingsStore } from "@/store/modules/settings"; | |||
| const settingsStore = useSettingsStore(); | |||
| defineProps({ | |||
| collapse: { | |||
| type: Boolean, | |||
| required: true | |||
| } | |||
| required: true, | |||
| }, | |||
| }); | |||
| const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href); | |||
| @@ -19,25 +19,33 @@ const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href); | |||
| <router-link | |||
| v-if="collapse" | |||
| key="collapse" | |||
| class="h-full w-full flex items-center justify-center" | |||
| class="h-full w-full flex items-center justify-center left-top-box" | |||
| to="/" | |||
| > | |||
| <img v-if="settingsStore.sidebarLogo" :src="logo" class="w-5 h-5" /> | |||
| <span v-else class="ml-3 text-white text-sm font-bold" | |||
| >vue3-element-admin</span | |||
| > | |||
| <!-- <img | |||
| v-if="settingsStore.sidebarLogo" | |||
| src="../../../assets/img/left-top-logo.png" | |||
| class="w-5 h-5" | |||
| /> --> | |||
| <img | |||
| v-if="settingsStore.sidebarLogo" | |||
| src="../../../assets/img/left-top-logo.png" | |||
| /> | |||
| <span v-else class="ml-3 text-white text-sm font-bold"></span> | |||
| </router-link> | |||
| <router-link | |||
| v-else | |||
| key="expand" | |||
| class="h-full w-full flex items-center justify-center" | |||
| class="h-full w-full flex items-center justify-center left-top-box" | |||
| to="/" | |||
| > | |||
| <img v-if="settingsStore.sidebarLogo" :src="logo" class="w-5 h-5" /> | |||
| <span class="ml-3 text-white text-sm font-bold" | |||
| >vue3-element-admin</span | |||
| > | |||
| <img | |||
| v-if="settingsStore.sidebarLogo" | |||
| src="../../../assets/img/left-top-logo.png" | |||
| class="left-top-logo" | |||
| /> | |||
| <span class="ml-3 text-white text-sm font-bold"></span> | |||
| </router-link> | |||
| </transition> | |||
| </div> | |||
| @@ -45,6 +53,17 @@ const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href); | |||
| <style lang="scss" scoped> | |||
| // https://cn.vuejs.org/guide/built-ins/transition.html#the-transition-component | |||
| .left-top-box { | |||
| background-color: #000; | |||
| } | |||
| .left-top-logo { | |||
| width: 180px; | |||
| height: 40px; | |||
| padding: 5px 0 0 10px; | |||
| } | |||
| .sidebarLogoFade-enter-active { | |||
| transition: opacity 2s; | |||
| } | |||
| @@ -1,5 +1,5 @@ | |||
| <script setup lang="ts"> | |||
| import { useRoute } from "vue-router"; | |||
| import { RouteLocationRaw, useRoute, useRouter } from "vue-router"; | |||
| import SidebarItem from "./SidebarItem.vue"; | |||
| import Logo from "./Logo.vue"; | |||
| @@ -10,19 +10,48 @@ import { useAppStore } from "@/store/modules/app"; | |||
| import { storeToRefs } from "pinia"; | |||
| import variables from "@/styles/variables.module.scss"; | |||
| // 静态路由 | |||
| import { constantRoutes } from "@/router"; | |||
| const settingsStore = useSettingsStore(); | |||
| const permissionStore = usePermissionStore(); | |||
| const appStore = useAppStore(); | |||
| const { sidebarLogo } = storeToRefs(settingsStore); | |||
| const route = useRoute(); | |||
| const router = useRouter(); | |||
| function routerTo(url: RouteLocationRaw) { | |||
| router.push(url); | |||
| } | |||
| </script> | |||
| <template> | |||
| <!-- 左侧菜单 --> | |||
| <div :class="{ 'has-logo': sidebarLogo }"> | |||
| <logo v-if="sidebarLogo" :collapse="!appStore.sidebar.opened" /> | |||
| <el-scrollbar> | |||
| <div class="myRouter"> | |||
| <div class="myRouter-item" @click="routerTo('/createVideo')"> | |||
| <div class="icon"> | |||
| <el-icon><i-ep-edit /></el-icon> | |||
| </div> | |||
| 创作视频 | |||
| </div> | |||
| <div class="myRouter-item" @click="routerTo('/myCreating')"> | |||
| <div class="icon"> | |||
| <el-icon><i-ep-menu /></el-icon> | |||
| </div> | |||
| 我的视频 | |||
| </div> | |||
| <div class="myRouter-item pricing" @click="routerTo('/myStore')"> | |||
| <div class="icon"> | |||
| <el-icon><i-ep-Goods /></el-icon> | |||
| </div> | |||
| 商店 | |||
| </div> | |||
| </div> | |||
| <!-- <el-scrollbar> | |||
| <el-menu | |||
| style="background-color: #000000" | |||
| :default-active="route.path" | |||
| :collapse="!appStore.sidebar.opened" | |||
| :background-color="variables.menuBg" | |||
| @@ -40,6 +69,76 @@ const route = useRoute(); | |||
| :is-collapse="!appStore.sidebar.opened" | |||
| /> | |||
| </el-menu> | |||
| </el-scrollbar> | |||
| </el-scrollbar> --> | |||
| </div> | |||
| </template> | |||
| <style lang="scss" scoped> | |||
| .myRouter { | |||
| position: relative; | |||
| height: calc(100% - 50px); | |||
| padding: 200px 20px 0; | |||
| color: #fff; | |||
| &-item { | |||
| display: flex; | |||
| width: 100%; | |||
| height: 50px; | |||
| padding-left: 20px; | |||
| font-size: 20px; | |||
| font-weight: 500; | |||
| line-height: 50px; | |||
| text-align: center; | |||
| cursor: pointer; | |||
| border-bottom: 2px solid #fff; | |||
| .icon { | |||
| width: 40px; | |||
| height: 40px; | |||
| color: #fff; | |||
| border-radius: 50%; | |||
| .el-icon { | |||
| width: 25px; | |||
| height: 25px; | |||
| font-size: 25px; | |||
| color: #fff; | |||
| text-align: center; | |||
| vertical-align: sub; | |||
| } | |||
| } | |||
| &:hover { | |||
| color: #000; | |||
| background-color: #fff; | |||
| .el-icon { | |||
| color: #000; | |||
| } | |||
| } | |||
| } | |||
| .pricing { | |||
| position: absolute; | |||
| bottom: 20px; | |||
| width: calc(100% - 40px); | |||
| text-align: center; | |||
| } | |||
| } | |||
| :deep(.el-sub-menu__title) { | |||
| background-color: #000 !important; | |||
| } | |||
| :deep(.el-menu-item) { | |||
| div { | |||
| background-color: #000 !important; | |||
| } | |||
| background-color: #000 !important; | |||
| } | |||
| :deep(.el-menu-item.is-active) { | |||
| color: #fff; | |||
| } | |||
| </style> | |||
| @@ -31,8 +31,13 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
| path: "createVideo", | |||
| component: () => import("@/views/createVideo/index.vue"), | |||
| name: "createVideo", | |||
| meta: { title: "createVideo", icon: "homepage", affix: true }, | |||
| } | |||
| meta: { | |||
| title: "createVideo", | |||
| icon: "homepage", | |||
| affix: true, | |||
| name: "创作视频", | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| // 视频列表 | |||
| @@ -45,8 +50,13 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
| path: "myCreating", | |||
| component: () => import("@/views/myCreating/index.vue"), | |||
| name: "myCreating", | |||
| meta: { title: "myCreating", icon: "homepage", affix: true }, | |||
| } | |||
| meta: { | |||
| title: "myCreating", | |||
| icon: "homepage", | |||
| affix: true, | |||
| name: "我的视频", | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| // 个人账户 | |||
| @@ -59,36 +69,52 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
| path: "myAccount", | |||
| component: () => import("@/views/myAccount/index.vue"), | |||
| name: "myAccount", | |||
| meta: { title: "myAccount", icon: "homepage", affix: true }, | |||
| } | |||
| meta: { | |||
| title: "myAccount", | |||
| icon: "homepage", | |||
| affix: true, | |||
| name: "个人账户", | |||
| }, | |||
| }, | |||
| ], | |||
| }, | |||
| // 商店 | |||
| { | |||
| path: "/dashboard", | |||
| path: "/", | |||
| component: Layout, | |||
| redirect: "/dashboard", | |||
| redirect: "/myStore", | |||
| children: [ | |||
| { | |||
| path: "dashboard", | |||
| component: () => import("@/views/dashboard/index.vue"), | |||
| name: "Dashboard", | |||
| meta: { title: "dashboard", icon: "homepage", affix: true }, | |||
| }, | |||
| { | |||
| path: "401", | |||
| component: () => import("@/views/error-page/401.vue"), | |||
| meta: { hidden: true }, | |||
| }, | |||
| { | |||
| path: "404", | |||
| component: () => import("@/views/error-page/404.vue"), | |||
| meta: { hidden: true }, | |||
| path: "myStore", | |||
| component: () => import("@/views/myStore/index.vue"), | |||
| name: "myStore", | |||
| meta: { title: "myStore", icon: "homepage", affix: true, name: "商店" }, | |||
| }, | |||
| ], | |||
| }, | |||
| // { | |||
| // path: "/dashboard", | |||
| // component: Layout, | |||
| // redirect: "/dashboard", | |||
| // children: [ | |||
| // { | |||
| // path: "dashboard", | |||
| // component: () => import("@/views/dashboard/index.vue"), | |||
| // name: "Dashboard", | |||
| // meta: { title: "dashboard", icon: "homepage", affix: true }, | |||
| // }, | |||
| // { | |||
| // path: "401", | |||
| // component: () => import("@/views/error-page/401.vue"), | |||
| // meta: { hidden: true }, | |||
| // }, | |||
| // { | |||
| // path: "404", | |||
| // component: () => import("@/views/error-page/404.vue"), | |||
| // meta: { hidden: true }, | |||
| // }, | |||
| // ], | |||
| // }, | |||
| // 外部链接 | |||
| /*{ | |||
| @@ -43,8 +43,8 @@ interface DefaultSettings { | |||
| const defaultSettings: DefaultSettings = { | |||
| title: "vue3-element-admin", | |||
| showSettings: true, | |||
| tagsView: true, | |||
| showSettings: false, | |||
| tagsView: false, | |||
| fixedHeader: false, | |||
| sidebarLogo: true, | |||
| layout: "left", | |||
| @@ -4,6 +4,7 @@ import { useStorage } from "@vueuse/core"; | |||
| export const useSettingsStore = defineStore("setting", () => { | |||
| // state | |||
| const tagsView = useStorage<boolean>("tagsView", defaultSettings.tagsView); | |||
| const showSettings = ref<boolean>(defaultSettings.showSettings); | |||
| @@ -37,6 +37,8 @@ | |||
| } | |||
| &.has-logo { | |||
| background-color: #000; | |||
| .el-scrollbar { | |||
| height: calc(100% - 50px); | |||
| } | |||
| @@ -4,10 +4,15 @@ | |||
| --menuBg: #304156; | |||
| --menuText: #bfcbd9; | |||
| --menuActiveText: #409eff; | |||
| --menuHover: #263445; | |||
| --subMenuBg: #1f2d3d; | |||
| // 左侧菜单鼠标经过颜色 | |||
| --menuHover: #000; | |||
| // --menuHover: #263445; | |||
| // 左侧子菜单颜色 | |||
| --subMenuBg: #000; | |||
| // --subMenuBg: #1f2d3d; | |||
| --subMenuActiveText: #f4f4f5; | |||
| --subMenuHover: #001528; | |||
| // --subMenuHover: #001528; | |||
| --subMenuHover: #000; | |||
| } | |||
| $menuBg: var(--menuBg); | |||
| @@ -5,6 +5,7 @@ declare global { | |||
| const ElForm: typeof import("element-plus/es")["ElForm"]; | |||
| const ElMessage: typeof import("element-plus/es")["ElMessage"]; | |||
| const ElMessageBox: typeof import("element-plus/es")["ElMessageBox"]; | |||
| const ElTree: typeof import("element-plus/es")["ElTree"]; | |||
| const asyncComputed: typeof import("@vueuse/core")["asyncComputed"]; | |||
| const autoResetRef: typeof import("@vueuse/core")["autoResetRef"]; | |||
| const computed: typeof import("vue")["computed"]; | |||
| @@ -278,6 +279,7 @@ declare module "vue" { | |||
| readonly ElMessageBox: UnwrapRef< | |||
| typeof import("element-plus/es")["ElMessageBox"] | |||
| >; | |||
| readonly ElTree: UnwrapRef<typeof import("element-plus/es")["ElTree"]>; | |||
| readonly asyncComputed: UnwrapRef< | |||
| typeof import("@vueuse/core")["asyncComputed"] | |||
| >; | |||
| @@ -11,6 +11,8 @@ declare module '@vue/runtime-core' { | |||
| ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] | |||
| ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] | |||
| ElButton: typeof import('element-plus/es')['ElButton'] | |||
| ElCard: typeof import('element-plus/es')['ElCard'] | |||
| ElCol: typeof import('element-plus/es')['ElCol'] | |||
| ElDialog: typeof import('element-plus/es')['ElDialog'] | |||
| ElDivider: typeof import('element-plus/es')['ElDivider'] | |||
| ElDropdown: typeof import('element-plus/es')['ElDropdown'] | |||
| @@ -20,17 +22,26 @@ declare module '@vue/runtime-core' { | |||
| ElFormItem: typeof import('element-plus/es')['ElFormItem'] | |||
| ElIcon: typeof import('element-plus/es')['ElIcon'] | |||
| ElInput: typeof import('element-plus/es')['ElInput'] | |||
| ElLink: typeof import('element-plus/es')['ElLink'] | |||
| ElMenu: typeof import('element-plus/es')['ElMenu'] | |||
| ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] | |||
| ElOption: typeof import('element-plus/es')['ElOption'] | |||
| ElPagination: typeof import('element-plus/es')['ElPagination'] | |||
| ElRadio: typeof import('element-plus/es')['ElRadio'] | |||
| ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] | |||
| ElRow: typeof import('element-plus/es')['ElRow'] | |||
| ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] | |||
| ElSelect: typeof import('element-plus/es')['ElSelect'] | |||
| ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] | |||
| ElSwitch: typeof import('element-plus/es')['ElSwitch'] | |||
| ElTable: typeof import('element-plus/es')['ElTable'] | |||
| ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] | |||
| ElTabPane: typeof import('element-plus/es')['ElTabPane'] | |||
| ElTabs: typeof import('element-plus/es')['ElTabs'] | |||
| ElTooltip: typeof import('element-plus/es')['ElTooltip'] | |||
| ElTree: typeof import('element-plus/es')['ElTree'] | |||
| ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] | |||
| ElUpload: typeof import('element-plus/es')['ElUpload'] | |||
| GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | |||
| Hamburger: typeof import('./../components/Hamburger/index.vue')['default'] | |||
| IconSelect: typeof import('./../components/IconSelect/index.vue')['default'] | |||
| @@ -39,8 +50,15 @@ declare module '@vue/runtime-core' { | |||
| IEpDelete: typeof import('~icons/ep/delete')['default'] | |||
| IEpDownload: typeof import('~icons/ep/download')['default'] | |||
| IEpEdit: typeof import('~icons/ep/edit')['default'] | |||
| IEpGoods: typeof import('~icons/ep/goods')['default'] | |||
| IEpMenu: typeof import('~icons/ep/menu')['default'] | |||
| IEpPlus: typeof import('~icons/ep/plus')['default'] | |||
| IEpRefresh: typeof import('~icons/ep/refresh')['default'] | |||
| IEpRefreshLeft: typeof import('~icons/ep/refresh-left')['default'] | |||
| IEpSearch: typeof import('~icons/ep/search')['default'] | |||
| IEpSetting: typeof import('~icons/ep/setting')['default'] | |||
| IEpTop: typeof import('~icons/ep/top')['default'] | |||
| IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default'] | |||
| IEpVideoPlay: typeof import('~icons/ep/video-play')['default'] | |||
| LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] | |||
| MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default'] | |||
| @@ -53,4 +71,7 @@ declare module '@vue/runtime-core' { | |||
| SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default'] | |||
| WangEditor: typeof import('./../components/WangEditor/index.vue')['default'] | |||
| } | |||
| export interface ComponentCustomProperties { | |||
| vLoading: typeof import('element-plus/es')['ElLoadingDirective'] | |||
| } | |||
| } | |||
| @@ -156,9 +156,10 @@ let languageOptions = reactive([ | |||
| <style lang="scss" scoped> | |||
| .page { | |||
| // height: calc(100vh - 84px); | |||
| height: 844px; | |||
| height: 887px; | |||
| padding: 20px 0 0 40px; | |||
| background-color: #fff; | |||
| border-radius: 25px 0 0; | |||
| } | |||
| .left { | |||
| @@ -79,10 +79,11 @@ | |||
| <script setup></script> | |||
| <style lang="scss" scoped> | |||
| .page { | |||
| height: 844px; | |||
| height: 887px; | |||
| padding: 20px 0 0 20px; | |||
| // height: calc(100vh - 84px); | |||
| background-color: #fff; | |||
| border-radius: 25px 0 0; | |||
| } | |||
| .left { | |||
| @@ -96,9 +96,11 @@ function mouseenter(item) { | |||
| <style lang="scss" scoped> | |||
| .page { | |||
| height: calc(100vh - 84px); | |||
| // height: calc(100vh - 84px); | |||
| height: 887px; | |||
| padding: 20px 0 0 20px; | |||
| background-color: #fff; | |||
| border-radius: 25px 0 0; | |||
| } | |||
| :deep(.el-input__wrapper) { | |||
| @@ -0,0 +1,16 @@ | |||
| <template> | |||
| <div class="page">商店</div> | |||
| </template> | |||
| <script setup> | |||
| let title = ref(""); | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .page { | |||
| // height: calc(100vh - 84px); | |||
| height: 887px; | |||
| padding: 20px 0 0 20px; | |||
| background-color: #fff; | |||
| border-radius: 25px 0 0; | |||
| } | |||
| </style> | |||