feat: enhance layout components, data layer and global styles
- SidebarRail, TopBar, FilterBar: improved navigation and filtering UX - metrics.js, requests.js: expanded data with multi-range trend series - composables: enhanced useChat, useNavigation, useRequests - global.css: refined design tokens and utility classes - Add DocFilterBar component and LoginView page Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<aside class="rail" aria-label="主导航">
|
||||
<div class="mark">RO</div>
|
||||
<div class="rail-brand">
|
||||
<div class="brand-mark">星</div>
|
||||
<div class="brand-copy">
|
||||
<strong>星海科技</strong>
|
||||
</div>
|
||||
<button class="brand-toggle" type="button" aria-label="打开合规对话" @click="emit('openChat')">
|
||||
<i class="pi pi-angle-left"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<nav class="rail-nav">
|
||||
<button
|
||||
v-for="item in navItems"
|
||||
@@ -8,30 +17,33 @@
|
||||
class="nav-btn"
|
||||
:class="{ active: activeView === item.id }"
|
||||
type="button"
|
||||
:aria-label="item.label"
|
||||
:title="item.label"
|
||||
@click="emit('navigate', item.id)"
|
||||
>
|
||||
<span v-html="item.icon"></span>
|
||||
<span class="nav-icon" v-html="item.icon"></span>
|
||||
<span class="nav-copy">
|
||||
<strong>{{ item.label }}</strong>
|
||||
</span>
|
||||
</button>
|
||||
</nav>
|
||||
<button class="nav-btn muted" type="button" aria-label="打开合规对话" title="打开合规对话" @click="emit('openChat')">
|
||||
<span v-html="messageIcon"></span>
|
||||
</button>
|
||||
|
||||
<div class="rail-user">
|
||||
<div class="user-avatar">张</div>
|
||||
<div class="user-copy">
|
||||
<strong>张晓明</strong>
|
||||
<span>财务管理员</span>
|
||||
</div>
|
||||
<i class="pi pi-angle-down"></i>
|
||||
</div>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { icons } from '../../data/icons.js'
|
||||
|
||||
defineProps({
|
||||
navItems: { type: Array, required: true },
|
||||
activeView: { type: String, required: true }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['navigate', 'openChat'])
|
||||
|
||||
const messageIcon = icons.message
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -41,30 +53,164 @@ const messageIcon = icons.message
|
||||
height: 100dvh;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
gap: 18px;
|
||||
padding: 18px 12px;
|
||||
background: var(--nav);
|
||||
color: #fff;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
background: #fff;
|
||||
border-right: 1px solid var(--line);
|
||||
z-index: 20;
|
||||
}
|
||||
.mark { width: 48px; height: 48px; display: grid; place-items: center; border-radius: 14px; background: linear-gradient(135deg,#fff,#9db2ff); color: #10215c; font-weight: 850; }
|
||||
.rail-nav { display: grid; gap: 10px; align-content: start; }
|
||||
.nav-btn {
|
||||
width: 48px;
|
||||
min-height: 48px;
|
||||
|
||||
.rail-brand,
|
||||
.rail-user {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.rail-brand {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.brand-mark,
|
||||
.user-avatar {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 6px;
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 999px;
|
||||
background: #e2f6ef;
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.brand-copy,
|
||||
.user-copy,
|
||||
.nav-copy {
|
||||
min-width: 0;
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.brand-copy strong,
|
||||
.user-copy strong,
|
||||
.nav-copy strong {
|
||||
color: var(--ink);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.user-copy span,
|
||||
.nav-copy small {
|
||||
margin-top: 2px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.brand-toggle {
|
||||
width: 28px;
|
||||
min-height: 28px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: var(--nav-muted);
|
||||
transition: background 160ms var(--ease), color 160ms var(--ease), transform 160ms var(--ease);
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.rail-nav {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
align-content: start;
|
||||
padding: 16px 12px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
width: 100%;
|
||||
min-height: 42px;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: #475569;
|
||||
text-align: left;
|
||||
transition: background 160ms var(--ease), color 160ms var(--ease);
|
||||
}
|
||||
|
||||
.nav-btn:hover,
|
||||
.nav-btn.active {
|
||||
background: rgba(16,185,129,.10);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.nav-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.nav-btn :deep(svg) {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2;
|
||||
fill: none;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.rail-user {
|
||||
padding: 16px;
|
||||
border-top: 1px solid var(--line);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.rail-user .pi {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.rail {
|
||||
position: relative;
|
||||
height: auto;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.rail-nav {
|
||||
grid-auto-flow: row;
|
||||
}
|
||||
}
|
||||
.nav-btn:hover, .nav-btn.active { background: rgba(255,255,255,.1); color: #fff; transform: translateY(-1px); }
|
||||
.nav-btn svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.rail { position: sticky; height: auto; grid-template-columns: auto 1fr auto; grid-template-rows: none; padding: 10px 12px; }
|
||||
.rail-nav { display: flex; overflow-x: auto; }
|
||||
.rail {
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid var(--line);
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.rail-nav {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
min-width: 190px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user