first commit
This commit is contained in:
259
src/views/Home/Index.vue
Normal file
259
src/views/Home/Index.vue
Normal file
@@ -0,0 +1,259 @@
|
||||
<template>
|
||||
<div class="mobile-home">
|
||||
<!-- 顶部Banner -->
|
||||
<div class="mobile-home__banner">
|
||||
<div class="mobile-home__banner-bg">
|
||||
<div class="mobile-home__banner-content">
|
||||
<div class="mobile-home__brand">
|
||||
<div class="mobile-home__brand-logo">亚为MOM</div>
|
||||
<div class="mobile-home__brand-text">
|
||||
<div class="mobile-home__brand-title">智能一体化管理系统</div>
|
||||
<div class="mobile-home__brand-sub">私有化部署,可定制</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile-home__banner-deco">
|
||||
<svg width="80" height="80" viewBox="0 0 80 80" fill="none">
|
||||
<rect x="10" y="20" width="25" height="35" rx="3" fill="rgba(255,255,255,0.3)"/>
|
||||
<rect x="40" y="10" width="30" height="45" rx="3" fill="rgba(255,255,255,0.2)"/>
|
||||
<circle cx="55" cy="60" r="15" fill="rgba(255,255,255,0.15)"/>
|
||||
<rect x="15" y="58" width="20" height="3" rx="1" fill="rgba(255,255,255,0.4)"/>
|
||||
<rect x="15" y="64" width="14" height="3" rx="1" fill="rgba(255,255,255,0.3)"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 常用功能区 -->
|
||||
<div class="mobile-home__section">
|
||||
<div class="mobile-home__section-header">
|
||||
<div class="mobile-home__section-icon">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" fill="#409eff">
|
||||
<path d="M3.5 18.49l6-6.01 4 4L22 6.92l-1.41-1.41-7.09 7.97-4-4L2 16.99z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="mobile-home__section-title">常用功能</span>
|
||||
</div>
|
||||
|
||||
<div class="mobile-home__grid" v-loading="loading">
|
||||
<div
|
||||
v-for="item in shortcut"
|
||||
:key="item.name"
|
||||
class="mobile-home__grid-item"
|
||||
@click="handleShortcutClick(item.url)"
|
||||
>
|
||||
<div class="mobile-home__grid-icon" :style="{ color: item.color, background: item.color + '18' }">
|
||||
<Icon :icon="item.icon" />
|
||||
</div>
|
||||
<span class="mobile-home__grid-label">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import type { Shortcut } from './types'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
defineOptions({ name: 'Index' })
|
||||
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const permissionStore = usePermissionStore()
|
||||
const loading = ref(true)
|
||||
const avatar = userStore.getUser.avatar
|
||||
const username = userStore.getUser.nickname
|
||||
|
||||
// 预设颜色列表
|
||||
const colorList = [
|
||||
'#1fdaca', '#ff6b6b', '#7c3aed', '#3fb27f', '#4daf1bc9', '#1a73e8',
|
||||
'#f59e0b', '#10b981', '#6366f1', '#ef4444', '#8b5cf6', '#06b6d4',
|
||||
'#84cc16', '#f97316', '#ec4899', '#14b8a6', '#22c55e', '#6b7280',
|
||||
'#3b82f6', '#fbbf24'
|
||||
]
|
||||
|
||||
// 获取快捷入口
|
||||
let shortcut = reactive<Shortcut[]>([])
|
||||
|
||||
// 递归提取所有叶子节点路由
|
||||
const extractLeafRoutes = (routes: any[], result: Shortcut[] = [], colorIndex = { value: 0 }, parentPath = ''): Shortcut[] => {
|
||||
routes.forEach((route) => {
|
||||
if (route.meta?.hidden) return
|
||||
let fullPath = route.path || ''
|
||||
if (fullPath && !fullPath.startsWith('/') && !fullPath.startsWith('http')) {
|
||||
fullPath = parentPath.endsWith('/') ? `${parentPath}${fullPath}` : `${parentPath}/${fullPath}`
|
||||
}
|
||||
if (fullPath && !fullPath.startsWith('/') && !fullPath.startsWith('http')) {
|
||||
fullPath = `/${fullPath}`
|
||||
}
|
||||
if (route.children && route.children.length > 0) {
|
||||
extractLeafRoutes(route.children, result, colorIndex, fullPath)
|
||||
} else {
|
||||
if (fullPath) {
|
||||
result.push({
|
||||
name: route.meta?.title || route.name || '未命名',
|
||||
icon: route.meta?.icon || 'mdi:application',
|
||||
url: fullPath,
|
||||
color: colorList[colorIndex.value % colorList.length]
|
||||
})
|
||||
colorIndex.value++
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
const getShortcut = async () => {
|
||||
const routes = permissionStore.getRouters
|
||||
const leafRoutes = extractLeafRoutes(routes)
|
||||
shortcut.splice(0, shortcut.length, ...leafRoutes)
|
||||
}
|
||||
|
||||
const getAllApi = async () => {
|
||||
await getShortcut()
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
const handleShortcutClick = (url: string) => {
|
||||
if (url.startsWith('http://') || url.startsWith('https://')) {
|
||||
window.open(url, '_blank')
|
||||
} else {
|
||||
router.push(url)
|
||||
}
|
||||
}
|
||||
|
||||
getAllApi()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.mobile-home {
|
||||
background: #f5f5f5;
|
||||
min-height: 100%;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Banner */
|
||||
.mobile-home__banner {
|
||||
padding: 0 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.mobile-home__banner-bg {
|
||||
background: linear-gradient(135deg, #43cea2 0%, #2a9d8f 50%, #264653 100%);
|
||||
border-radius: 0 0 16px 16px;
|
||||
padding: 20px 16px 24px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.mobile-home__banner-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.mobile-home__brand {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.mobile-home__brand-logo {
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
letter-spacing: 2px;
|
||||
text-shadow: 0 2px 8px rgba(0,0,0,0.2);
|
||||
}
|
||||
.mobile-home__brand-text {
|
||||
color: #fff;
|
||||
}
|
||||
.mobile-home__brand-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.mobile-home__brand-sub {
|
||||
font-size: 12px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.mobile-home__banner-deco {
|
||||
opacity: 0.7;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 功能区 */
|
||||
.mobile-home__section {
|
||||
margin: 0 12px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 14px;
|
||||
box-shadow: 0 1px 4px rgba(0,0,0,0.06);
|
||||
}
|
||||
.mobile-home__section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 2px solid #409eff;
|
||||
}
|
||||
.mobile-home__section-icon {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: rgba(64,158,255,0.1);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.mobile-home__section-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
/* 功能网格 */
|
||||
.mobile-home__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 16px 8px;
|
||||
min-height: 100px;
|
||||
}
|
||||
.mobile-home__grid-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
.mobile-home__grid-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22px;
|
||||
transition: transform 0.2s;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
}
|
||||
.mobile-home__grid-label {
|
||||
font-size: 11px;
|
||||
color: #303133;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
max-width: 64px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user