一、基本概念

二、运行效果及部分代码

1、运行效果

2、代码目录

3、部分代码

APP.VUE

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <router-view></router-view>
</template>

Login.vue

<template>
  <div class="login-container">
    <div class="login-box">
      <div class="avatar-box">
        <img src="../assets/logo.png" alt="logo" class="avatar">
      </div>
      <div class="form-login">
        <div class="form-group">
          <label for="username">登录名称:</label>
          <input type="text" id="username" placeholder="请输入登录名称" autocomplete="off" v-model.trim="username">
        </div>
        <div class="form-group">
          <label for="password">登录密码:</label>
          <input type="password" id="password" placeholder="请输入登录密码" v-model.trim="password">
        </div>
        <div class="form-group">
          <button class="btn" @click="onLogin">登录</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'

const username = ref('')
const password = ref('')
const router = useRouter()

const onLogin = () => {
  if (username.value === 'admin' && password.value === '123456') {
    localStorage.setItem('token', 'Bearer xxx')
    router.push('/home')
  } else {
    alert('用户名或密码输入错误')
    localStorage.removeItem('token')
  }
}
</script>

<style scoped lang="less">
.login-container {
  width: 100vw;
  height: 100vh;
  background: #f5f5f5;
  display: flex;
  justify-content: center;
  align-items: center;
}
.login-box {
  width: 360px;
  padding: 30px;
  background: #fff;
  border-radius: 8px;
}
.avatar-box {
  text-align: center;
  margin-bottom: 20px;
  .avatar {
    width: 80px;
  }
}
.form-group {
  margin: 15px 0;
  display: flex;
  flex-direction: column;
  gap:6px;
  input {
    padding:8px;
    border:1px solid #ccc;
    border-radius:4px;
  }
  .btn {
    padding:9px;
    background:#409eff;
    color:#fff;
    border:none;
    border-radius:4px;
    cursor:pointer;
  }
}
</style>

Home.vue

<template>
  <div class="home-wrap">
    <!--头部-->
    <MyHeader></MyHeader>
    <div class="main-content">
      <!--侧边栏-->
      <MyAside></MyAside>
      <!--内容区域-->
      <div class="page-main">
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script setup>
import MyHeader from './subcomponents/MyHeader.vue'
import MyAside from './subcomponents/MyAside.vue'
</script>

<style scoped lang="less">
.home-wrap {
  height: 100vh;
  display: flex;
  flex-direction: column;
}
.main-content {
  flex:1;
  display:flex;
  .page-main {
    flex:1;
    padding:15px;
    background:#f6f6f6;
  }
}
</style>

MyHeader.vue

<template>
  <div class="layout-header-container">
    <div class="layout-header-left">
      <img src="../../assets/logo.png" class="logo-img" alt="">
      <h4>商城后台管理系统</h4>
    </div>
    <div class="layout-header-right">
      <button @click="onLogout">退出</button>
    </div>
  </div>
</template>

<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const onLogout = () => {
  localStorage.removeItem('token')
  router.push('/login')
}
</script>

<style scoped lang="less">
.layout-header-container {
  height:60px;
  background:#409eff;
  display:flex;
  justify-content:space-between;
  align-items:center;
  padding:0 20px;
  color:#fff;
  .layout-header-left {
    display:flex;
    align-items:center;
    gap:10px;
    .logo-img {
      width:36px;
    }
  }
  button {
    padding:5px 12px;
    border:none;
    border-radius:3px;
    cursor:pointer;
  }
}
</style>

MyAside.vue

<template>
  <div class="layout-aside-container">
    <ul class="menu">
      <li class="menu-item">
        <router-link to="/home/users">用户管理</router-link>
      </li>
      <li class="menu-item">
        <router-link to="/home/rights">权限管理</router-link>
      </li>
      <li class="menu-item">
        <router-link to="/home/goods">商品管理</router-link>
      </li>
      <li class="menu-item">
        <router-link to="/home/orders">订单管理</router-link>
      </li>
      <li class="menu-item">
        <router-link to="/home/settings">系统设置</router-link>
      </li>
    </ul>
  </div>
</template>

<script setup>
</script>

<style scoped lang="less">
.layout-aside-container {
  width:180px;
  background:#304156;
  .menu {
    padding:0;
    margin:0;
    list-style:none;
    .menu-item {
      a {
        display:block;
        padding:14px 20px;
        color:#bfcbd9;
        text-decoration:none;
        &.router-link-active {
          background:#263445;
          color:#409eff;
        }
      }
    }
  }
}
</style>

router.js 代码

import { createRouter, createWebHashHistory, RouterView } from 'vue-router'
import { h } from 'vue'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      redirect: '/login'
    },
    {
      path: '/login',
      component: () => import('./components/Login.vue')
    },
    {
      path: '/home',
      component: () => import('./components/Home.vue'),
      redirect: '/home/users',
      children: [
        {
          path: 'users',
          component: {
            render() {
              // 我这里没有自己的页面,我只是一个 “容器”,用来显示我下面的子页面。
              return h(RouterView)
            }
          },
          children: [
            { path: '', component: () => import('./components/subcomponents/MyUsers.vue') },
            { path: ':id', component: () => import('./components/user/MyUserDetail.vue'), props: true }
          ]
        },
        {
          path: 'rights',
          component: () => import('./components/subcomponents/MyRights.vue')
        },
        {
          path: 'goods',
          component: () => import('./components/subcomponents/MyGoods.vue')
        },
        {
          path: 'orders',
          component: () => import('./components/subcomponents/MyOrders.vue')
        },
        {
          path: 'settings',
          component: () => import('./components/subcomponents/MySettings.vue')
        }
      ]
    }
  ]
})

// 路由守卫
router.beforeEach((to, from, next) => {
  if (to.path === '/login') {
    next()
  } else {
    const token = localStorage.getItem('token')
    token ? next() : next('/login')
  }
})

export default router

main.js 代码

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ScopeSlot from './components/ScopeSlot.vue'
// 引入element-plus核心样式
import 'element-plus/dist/index.css'
import ElementPlus from 'element-plus'
const app = createApp(App)
app.use(ElementPlus).use(router)
app.mount('#app')

需要安装的组件

npm instal  vue-router
npm instal   element-plus
npm install less

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐