| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <div class="layout">
- <!-- 左侧菜单 -->
- <aside class="sidebar">
- <div class="brand">
- <!-- <div class="brand-icon">申</div> -->
- <div class="brand-icon"><img :src="logo" alt="logo" style="width: 40px; height: 40px;" /></div>
- <div>
- <strong>申勤物业</strong>
- <span>数字化平台</span>
- </div>
- </div>
- <nav class="nav">
- <div v-for="item in navItems" :key="item.path" @click="handleClick(item.path)">
- <router-link
- v-if="item.path !== 'nav-label'"
- :class="{ active: $route.path === item.path }"
- :to="item.path"
- >
- {{ item.name }}
- </router-link>
- <div v-else class="nav-label">
- {{ item.name }}
- </div>
- </div>
- </nav>
-
- </aside>
- <!-- 右侧内容区 -->
- <div class="main">
- <!-- 顶部导航 -->
- <header class="topbar">
- <div>
- <h1>{{ currentTitle }}</h1>
- <p>{{ currentSubtitle }}</p>
- </div>
- <!-- <el-input
- v-model="searchText"
- placeholder="搜索项目、人员…"
- class="search-input"
- /> -->
- <div class="sidebar-footer">
- <el-dropdown @command="handleLogout">
- <span class="el-dropdown-link">
- <el-icon :size="20" color="var(--text2)">
- <UserFilled />
- </el-icon>
- <span style="padding: 0 6px">
- {{userName}}
- </span>
- </span>
- <template #dropdown>
- <el-dropdown-menu>
- <!-- <el-dropdown-item command="login">账号登录</el-dropdown-item> -->
- <el-dropdown-item command="logout">退出登录</el-dropdown-item
- >
- </el-dropdown-menu>
- </template>
- </el-dropdown>
- </div>
- </header>
- <!-- 路由内容 -->
- <div :class="isGis == '/onemap' ? 'content-gis' : 'content'">
- <router-view />
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { computed, ref } from 'vue'
- import { useRouter } from 'vue-router'
- import { ElMessage } from 'element-plus'
- import { useUserStore } from '@/stores/user'
- import { UserFilled } from '@element-plus/icons-vue'
- const logo = new URL('/static/image/logo.png', import.meta.url).href
- const userStore = useUserStore()
- const router = useRouter()
- const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
- const userName = userInfo?.username =='user_xtw' ? '徐天炜' : userInfo?.username || ''
- const navItems = [
- { path: '/dashboard', name: '工作台' },
- { path: '/onemap', name: '空间一张图' },
- { path: '/projects', name: '项目台账' },
- { path: 'nav-label', name: '市场拓展' },
- { path: '/market', name: '市场拓展中心' },
- { path: '/renewal', name: '标书编制' },
- { path: '/tender-pool', name: '招标监测' },
- { path: '/bid-result', name: '开标与中标' }
- ]
- const isGis = ref('')
- const currentTitle = computed(() => {
- // sessionStorage.setItem('activeTab','ongoing')
- const item = navItems.find(n => n.path === router.currentRoute.value.path)
- isGis.value = item?.path ?? ''
- if(!item){
- return sessionStorage.getItem('name')
- }else{
- return item ? item.name : '工作台'
- }
- })
- const handleClick = (_path: string) => {
- sessionStorage.setItem('activeTab','ongoing')
- }
- const currentSubtitle = computed(() => {
- if (router.currentRoute.value.path === '/dashboard') {
- return '今日待办与关键指标 · 续标预警优先展示'
- }else if (router.currentRoute.value.path === '/onemap') {
- return '数据可视化平台 · 空间一张图'
- }else if (router.currentRoute.value.path === '/projects') {
- return '在管项目一览'
- }else if (router.currentRoute.value.path === '/market') {
- return '招标监测 · 标书编制 · 投标履约 · 项目续标'
- }else if (router.currentRoute.value.path === '/renewal') {
- return '合同到期预警 · 续标全流程跟进'
- }else if (router.currentRoute.value.path === '/tender-pool') {
- return '政府采购网抓取 · 续标监控 · 智能匹配'
- }else if (router.currentRoute.value.path === '/bid-workbench') {
- return '需求拆解 · 数据映射 · 分步确认 · 生成导出'
- }else if (router.currentRoute.value.path === '/bid-result') {
- return '投标登记 · 开标监控 · 结果抓取 · 中标推送'
- }else if (router.currentRoute.value.path.includes('project-detail/') || router.currentRoute.value.path.includes('renewal-detail/') || router.currentRoute.value.path.includes('renewal-expire-detail/')) {
- const addr = (sessionStorage.getItem('projectName'))
- return addr
- }else {
- return '欢迎使用申勤物业数字化平台'
- }
- })
- const handleLogout = () => {
- userStore.logout()
- ElMessage.success('已退出登录')
- router.push('/')
- }
- </script>
- <style scoped>
- .layout {
- display: flex;
- min-height: 100vh;
- }
- .sidebar {
- width: 220px;
- flex-shrink: 0;
- background: var(--surface);
- border-right: 1px solid var(--border);
- padding: 16px 12px;
- display: flex;
- flex-direction: column;
- }
- .brand {
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 8px 10px 20px;
- }
- .brand-icon {
- width: 36px;
- height: 36px;
- /* background: var(--primary); */
- border-radius: 8px;
- color: #fff;
- display: flex;
- align-items: center;
- justify-content: center;
- font-weight: 700;
- font-size: 14px;
- }
- .brand strong {
- display: block;
- font-size: 14px;
- }
- .brand span {
- font-size: 11px;
- color: var(--text3);
- }
- .nav {
- flex: 1;
- }
- .nav a {
- display: block;
- padding: 8px 12px;
- border-radius: 6px;
- color: var(--text2);
- font-size: 13px;
- margin-bottom: 2px;
- text-decoration: none;
- }
- .nav a:hover {
- background: #f8fafb;
- color: var(--text);
- }
- .nav a.active {
- background: var(--primary-soft);
- color: var(--primary);
- font-weight: 500;
- }
- .nav-label {
- font-size: 11px;
- color: var(--text3);
- padding: 12px 12px 6px;
- font-weight: 600;
- }
- .sidebar-footer {
- display: flex;
- cursor: pointer;
- align-items: center;
- font-size: 16px;
- color: var(--text3);
- }
- .sidebar-footer:hover {
- color: var(--primary);
- }
- .sidebar-footer .el-dropdown-link {
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .main {
- flex: 1;
- display: flex;
- flex-direction: column;
- min-width: 0;
- background: var(--bg);
- overflow: hidden;
- }
- .topbar {
- min-height: 52px;
- background: var(--surface);
- border-bottom: 1px solid var(--border);
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 10px 24px;
- gap: 16px;
- flex-wrap: wrap;
- }
- .topbar h1 {
- font-size: 17px;
- font-weight: 600;
- }
- .topbar p {
- font-size: 12px;
- color: var(--text3);
- }
- .search-input {
- width: 240px;
- }
- .content {
- padding: 20px 24px 32px;
- /* flex: 1; */
- height: calc(100vh - 70px);
- overflow-y: auto;
- }
- .content-gis {
- padding: 0 0;
- /* flex: 1; */
- /* height: calc(70px); */
- height: 100%;
- overflow-y: auto;
- }
- .el-dropdown-link {
- cursor: pointer;
- color: var(--text3);
- display: flex;
- align-items: center;
- border: 0;
- }
- .el-dropdown,
- .el-dropdown * {
- outline: none !important; /* 确保下拉触发器没有轮廓 */
- }
- @media (max-width: 768px) {
- .sidebar {
- width: 60px;
- }
- .brand span, .brand strong, .nav a, .sidebar-footer span {
- display: none;
- }
- }
- </style>
|