完善首页显示
This commit is contained in:
109
src/components/index/Datascreen.vue
Normal file
109
src/components/index/Datascreen.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<header class="header">
|
||||
<div class="header-left">
|
||||
<button class="header-button create-datascreen"><i class="fa-solid fa-plus"></i> 创建大屏</button>
|
||||
<button class="header-button import-datascreen"><i class="fa-solid fa-file-import"></i> 导入大屏</button>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<input type="text" placeholder="请输入名称" class="header-search"></input>
|
||||
<button class="header-button search-button"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
</div>
|
||||
</header>
|
||||
<main class="main">
|
||||
<div class="no-data">
|
||||
<i class="fa-solid fa-circle-xmark"></i>
|
||||
<span>暂无数据</span>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
<style>
|
||||
.header-left {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 15px;
|
||||
}
|
||||
.header-right {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
.header-button {
|
||||
width: 120px;
|
||||
height: 32px;
|
||||
font-size: 15px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
.header-button:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.header-button:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
.create-datascreen {
|
||||
color: #fff;
|
||||
background-color: #00b7ff;
|
||||
}
|
||||
.create-datascreen:hover {
|
||||
background-color: #00a2e2;
|
||||
}
|
||||
.create-datascreen:active {
|
||||
background-color: #0088c3;
|
||||
}
|
||||
.import-datascreen {
|
||||
color: #fff;
|
||||
background-color: #f472b6;
|
||||
}
|
||||
.import-datascreen:hover,
|
||||
.search-button:hover {
|
||||
background-color: #e267a7;
|
||||
}
|
||||
.import-datascreen:active,
|
||||
.search-button:active {
|
||||
background-color: #c35b99;
|
||||
}
|
||||
.header-search {
|
||||
width: 150px;
|
||||
height: 32px;
|
||||
font-size: 15px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
padding: 0 10px;
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
}
|
||||
.header-search:hover {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
.header-search:focus {
|
||||
outline: none;
|
||||
background-color: rgba(255,255,255,0.5);
|
||||
}
|
||||
.search-button {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
background-color: #f472b6;
|
||||
color: #fff;
|
||||
}
|
||||
.main {
|
||||
height: calc(100vh - 62px);
|
||||
padding-top: 62px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.no-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
font-size: 20px;
|
||||
}
|
||||
.no-data i {
|
||||
font-size: 64px;
|
||||
margin-bottom: 16px;
|
||||
color: #0095cf;
|
||||
}
|
||||
.no-data span {
|
||||
color: #00354a;
|
||||
}
|
||||
</style>
|
||||
@@ -1,16 +1,40 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { Eleme } from '@element-plus/icons-vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const handleMenuClick = (path) => {
|
||||
router.push(path)
|
||||
}
|
||||
|
||||
const activeMenu = computed(() => {
|
||||
const path = route.path
|
||||
if (path === '/' || path === '/datascreen') return '/datascreen'
|
||||
if (path.startsWith('/category')) return '/category'
|
||||
if (path.startsWith('/datasource')) return '/datasource'
|
||||
if (path.startsWith('/record')) return '/record'
|
||||
if (path.startsWith('/components')) return '/components'
|
||||
if (path.startsWith('/variables')) return '/variables'
|
||||
if (path.startsWith('/files')) return '/files'
|
||||
if (path.startsWith('/maps')) return '/maps'
|
||||
if (path.startsWith('/tools')) return '/tools'
|
||||
return ''
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="leftbar">
|
||||
<button class="leftbar-item"><i class="fa-solid fa-table-cells-large"></i> 大屏管理</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-folder"></i> 大屏分类</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-database"></i> 数据源管理</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-suitcase"></i> 数据集管理</button>
|
||||
<button class="leftbar-item"><el-icon style="font-size:20px;transform: translateY(4px);"><Eleme /></el-icon> 组件库</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-lightbulb"></i> 全局变量</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-layer-group"></i> 静态资源</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-location-dot"></i> 地图管理</button>
|
||||
<button class="leftbar-item"><i class="fa-solid fa-boxes-stacked"></i> 工具箱</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/datascreen' }" @click="handleMenuClick('/datascreen')"><i class="fa-solid fa-table-cells-large"></i> 大屏管理</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/category' }" @click="handleMenuClick('/category')"><i class="fa-solid fa-folder"></i> 大屏分类</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/datasource' }" @click="handleMenuClick('/datasource')"><i class="fa-solid fa-database"></i> 数据源管理</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/record' }" @click="handleMenuClick('/record')"><i class="fa-solid fa-suitcase"></i> 数据集管理</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/components' }" @click="handleMenuClick('/components')"><el-icon style="font-size:20px;transform: translateY(4px);"><Eleme /></el-icon> 组件库</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/variables' }" @click="handleMenuClick('/variables')"><i class="fa-solid fa-lightbulb"></i> 全局变量</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/files' }" @click="handleMenuClick('/files')"><i class="fa-solid fa-layer-group"></i> 静态资源</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/maps' }" @click="handleMenuClick('/maps')"><i class="fa-solid fa-location-dot"></i> 地图管理</button>
|
||||
<button class="leftbar-item" :class="{ 'activated': activeMenu === '/tools' }" @click="handleMenuClick('/tools')"><i class="fa-solid fa-boxes-stacked"></i> 工具箱</button>
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
@@ -21,13 +45,19 @@
|
||||
border-radius: 16px;
|
||||
width: 200px;
|
||||
height: calc(100% - 48px);
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
backdrop-filter: blur(3px);
|
||||
background-color: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(10px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(10px) saturate(180%);
|
||||
border: 1px solid rgba(255,255,255,0.4);
|
||||
box-shadow:
|
||||
0 8px 32px rgba(0,0,0,0.2),
|
||||
inset 0 4px 20px rgba(255,255,255,0.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 8px;
|
||||
box-sizing: border-box;
|
||||
z-index: 2;
|
||||
}
|
||||
.leftbar-item {
|
||||
width: 90%;
|
||||
@@ -43,7 +73,8 @@
|
||||
.leftbar-item:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
}
|
||||
.leftbar-item:active {
|
||||
.leftbar-item:active,
|
||||
.activated {
|
||||
background-color: rgba(255,255,255,0.4);
|
||||
}
|
||||
</style>
|
||||
@@ -21,6 +21,7 @@ onMounted(() => {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
}
|
||||
.title {
|
||||
position: fixed;
|
||||
|
||||
36
src/components/index/Main.vue
Normal file
36
src/components/index/Main.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup>
|
||||
import { defineAsyncComponent, computed } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
const route = useRoute()
|
||||
const DynamicContent = computed(() => {
|
||||
switch (route.path) {
|
||||
case '/':
|
||||
case '/datascreen':
|
||||
return defineAsyncComponent(() => import('@/components/index/Datascreen.vue'))
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<div class="container">
|
||||
<component :is="DynamicContent" />
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.container {
|
||||
position: fixed;
|
||||
top: 38px;
|
||||
left: 216px;
|
||||
border-radius: 16px;
|
||||
width: calc(100vw - 224px);
|
||||
height: calc(100vh - 48px);
|
||||
background-color: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(10px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(10px) saturate(180%);
|
||||
border: 1px solid rgba(255,255,255,0.4);
|
||||
box-shadow:
|
||||
0 8px 32px rgba(0,0,0,0.2),
|
||||
inset 0 4px 20px rgba(255,255,255,0.3);
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
@@ -43,8 +43,10 @@ onUnmounted(() => {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
background-color: rgba(255,255,255,0.15);
|
||||
backdrop-filter: blur(3px);
|
||||
-webkit-backdrop-filter: blur(3px);
|
||||
z-index: 2;
|
||||
}
|
||||
.logo {
|
||||
position: fixed;
|
||||
|
||||
@@ -32,15 +32,60 @@ const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: '/' || '/index.html',
|
||||
name: 'index',
|
||||
component: () => import('./views/Index.vue'),
|
||||
meta: { requiresIndexLoading: true },
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: () => import('./views/Loading.vue'),
|
||||
meta: { requiresIndexLoading: true }
|
||||
},
|
||||
{
|
||||
path: '/datascreen',
|
||||
name: 'Datascreen',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/category',
|
||||
name: 'Category',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/datasource',
|
||||
name: 'Datasource',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/record',
|
||||
name: 'Record',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/components',
|
||||
name: 'Components',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/variables',
|
||||
name: 'Variables',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/files',
|
||||
name: 'Files',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/maps',
|
||||
name: 'Maps',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/tools',
|
||||
name: 'Tools',
|
||||
component: () => import('./views/Index.vue')
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'NotFound',
|
||||
component: () => import('./views/NotFound.vue'),
|
||||
component: () => import('./views/NotFound.vue')
|
||||
},
|
||||
],
|
||||
})
|
||||
@@ -48,22 +93,19 @@ const router = createRouter({
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
if (!to.meta.requiresIndexLoading) {
|
||||
NProgress.start()
|
||||
}
|
||||
|
||||
if (to.meta.requiresIndexLoading) {
|
||||
} else {
|
||||
NProgress.done()
|
||||
NProgress.remove()
|
||||
|
||||
loadingNode = document.createElement('div');
|
||||
loadingNode.id = 'custom-loading';
|
||||
document.body.appendChild(loadingNode);
|
||||
|
||||
try {
|
||||
const LoadingComponent = (await import('@/components/index/Loading.vue')).default;
|
||||
|
||||
loadingApp = createApp({
|
||||
render: () => h(LoadingComponent)
|
||||
});
|
||||
|
||||
loadingApp.mount(loadingNode);
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom loading component:', error);
|
||||
@@ -88,7 +130,7 @@ router.afterEach((to) => {
|
||||
document.body.removeChild(loadingNode);
|
||||
loadingNode = null;
|
||||
}
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
if (!to.meta.requiresIndexLoading && NProgress.isStarted()) {
|
||||
|
||||
@@ -9,14 +9,27 @@ const config = getConfig()
|
||||
|
||||
const Topbar = defineAsyncComponent(() => import('@/components/index/Topbar.vue'))
|
||||
const Leftbar = defineAsyncComponent(() => import('@/components/index/Leftbar.vue'))
|
||||
const Main = defineAsyncComponent(() => import('@/components/index/Main.vue'))
|
||||
|
||||
onMounted(() => {
|
||||
document.title = config.title
|
||||
document.body.style.background = "url('"+config.backgroundImg+"') no-repeat center center fixed"
|
||||
document.body.style.backgroundSize = "cover"
|
||||
|
||||
const linkElement = document.createElement('link');
|
||||
linkElement.rel = 'stylesheet';
|
||||
|
||||
if (config.cdnUrl && config.cdnUrl !== "") {
|
||||
linkElement.href = `${config.cdnUrl}/assets/font-awesome/css/all.min.css`;
|
||||
} else {
|
||||
linkElement.href = '@/assets/font-awesome/css/all.min.css';
|
||||
}
|
||||
|
||||
document.head.appendChild(linkElement);
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<Topbar />
|
||||
<Leftbar />
|
||||
<Main />
|
||||
</template>
|
||||
19
src/views/Loading.vue
Normal file
19
src/views/Loading.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup>
|
||||
import { onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
let timer = null
|
||||
|
||||
onMounted(() => {
|
||||
timer = setTimeout(() => {
|
||||
router.push('/datascreen')
|
||||
}, 3000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -54,8 +54,13 @@ onMounted(() => {
|
||||
height: 80%;
|
||||
border-radius: 20px;
|
||||
backdrop-filter: blur(3px);
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2);
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(10px) saturate(180%);
|
||||
-webkit-backdrop-filter: blur(10px) saturate(180%);
|
||||
border: 1px solid rgba(255,255,255,0.4);
|
||||
box-shadow:
|
||||
0 8px 32px rgba(0,0,0,0.2),
|
||||
inset 0 4px 20px rgba(255,255,255,0.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
Reference in New Issue
Block a user