从0开始创建一个管理系统

232 阅读4分钟

前言

一直以来都是接触的半成品项目,最近终于有机会从0开始搞一个项目,网上好多框架,但是内容比较多,感觉不太适合一些简单项目。所以想着基于vue-cli自己搭建一个简单的管理系统模板框架以供以后使用。

1.技术选型

本项目是基于@vue/cli 5.0.4 + vue2来搭建

Node 版本要求 Vue CLI 4.x 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。你可以使用 nnvm 或 nvm-windows 在同一台电脑中管理多个 Node 版本。

本项目node版本为v12.22.12

2.初始化项目

安装vue-cli

全局安装vue-cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli

创建项目

vue create front-end-admin

image.png

? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS
Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 2.x
? Use history mode for router? (Requires proper server setup for index fallback
in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported
by default): Sass/SCSS (with dart-sass)
? Pick a linter / formatter config: Standard
? Pick additional lint features: Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated
config files
? Save this as a preset for future projects? No


Vue CLI v5.0.4
✨  Creating project in E:\project\front-end-admin.
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...


> yorkie@2.0.0 install E:\project\front-end-admin\node_modules\yorkie
> node bin/install.js

setting up Git hooks
done


> core-js@3.23.5 postinstall E:\project\front-end-admin\node_modules\core-js
> node -e "try{require('./postinstall')}catch(e){}"

added 846 packages from 463 contributors in 52.731s

88 packages are looking for funding
  run `npm fund` for details

🚀  Invoking generators...
📦  Installing additional dependencies...

added 149 packages from 86 contributors in 13.827s

127 packages are looking for funding
  run `npm fund` for details

⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project front-end-admin.
👉  Get started with the following commands:

 $ cd front-end-admin
 $ npm run serve

此时安装完成,启动项目

 $ cd front-end-admin
 $ npm run serve
 
   App running at:
  - Local:   http://localhost:8080/
  - Network: http://172.16.13.249:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.

启动项目完成打开http://localhost:8080/ 如果你能出现以下画面恭喜你创建项目成功了

image.png

目录结构说明

├── .git  # git管理-初始化git之后会有,便于提交代码
├── node_modules # 第三方依赖包
├── public # 静态资源⽬录,任何放置在 public ⽂件夹的静态资源都会被简单的复制,⽽不经过 webpack,一些不被处理的文件放在此处
│ ├── favicon.ico # 网页图标
│ └── index.html # 主页
├── src # 项目核心文件(我们写的主要的代码都放在此处)
│ ├── assets # 公共资源⽬录,放图⽚等资源
│ ├── components # 存放公共组件
│ ├── router # 路由相关
│ ├── store # 容器相关
│ ├── views # 业务组件目录
│ ├── App.vue # 根组件,最终被替换渲染到 index.html ⻚⾯中 #app ⼊⼝ 节点 
│ ├── main.js # 整个项⽬的启动⼊⼝模块 
├── .browserslistrc # 指定了项⽬的⽬标浏览器的范围。这个值会被 @babel/pre set-env 和 Autoprefixer ⽤来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀
├── .editorconfig # EditorConfig 帮助开发⼈员定义和维护跨编辑器(或IDE) 的统⼀的代码⻛格
├── .eslintrc.js # ESLint 的配置⽂件
├── .gitignore # Git 的忽略配置⽂件,告诉Git项⽬中要忽略的⽂件或⽂件夹
├── babel.config.js # Babel 配置⽂件
|—— jsconfig.json  # javaScript 配置文件
├── package-lock.json # 记录安装时的包的版本号,以保证⾃⼰或其他⼈在 npm i nstall 时⼤家的依赖能保证⼀致
├── package.json # 包说明⽂件,记录了项⽬中使⽤到的第三⽅包依赖信息等内容
├── vue.config # webpack 配置文件(与webpack.config.js作用一致)
├── README.md # 说明⽂档

3.重构页面

由于默认⽣成的⽬录结构不满⾜我们的开发需求,所以需要做⼀些⾃定义改动。 这⾥主要处理下⾯的内容:

删除初始化的默认⽂件 
src/views/About.vue 
src/views/Home.vue 
src/components/Hello World.vue 
src/assets/logo.png
新增调整我们需要的⽬录结构
src/api ⽬录,接⼝模块 
src/utils ⽬录,存储⼀些⼯具模块 
src/styles ⽬录,存储⼀些样式资源

此时打开App.vue会有警告

image.png

只需要在jsconfig.json中配置 "jsx": "preserve"即可解决

4. 布局

导⼊ Element 组件库

1、安装 element
npm i element-ui --save
2、在 main.js 中导⼊配置
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI)
Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

初始化路由⻚⾯组件

LayOut页面

<template>
  <el-container  class="wrapper">
    <el-aside width="200px">
      <side-bar />
    </el-aside>
    <el-container>
      <el-header>
        <nav-bar />
      </el-header>
      <el-main>
        <!-- 子路由出口 -->
        <transition name="fade-transform" mode="out-in">
          <router-view :key="key" />
        </transition>
      </el-main>
    </el-container>
  </el-container>
</template>

<script>
import { NavBar, SideBar } from './components'
export default {
  name: 'LayoutIndex',
  computed: {
    key () {
      return this.$route.path
    }
  },
  components: {
    NavBar,
    SideBar
  },
  methods: {
  }
}
</script>

<style lang="scss" scoped>
.el-container {
  min-height: 100vh;
  // min-width: 980px;
}

.el-aside {
  background: #d3dce6;
}

.el-header {
  background: #fff;
}

.el-main {
  background: #e9eef3;
}
</style>

NarBar页面

<template>
  <div class="header">
    <bread-crumb class="breadcrumb-container" />
    <el-dropdown>
      <span class="el-dropdown-link">
        <el-avatar
          shape="square"
          :size="40"
        ></el-avatar>
        <i class="el-icon-arrow-down el-icon--right"></i>
      </span>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>{{ userInfo.userName }}</el-dropdown-item>
        <el-dropdown-item
          divided
          @click.native="handleLogout"
        >退出</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
  </div>
</template>

<script>
import Vue from 'vue'
import BreadCrumb from '@/components/Breadcrumb/index.vue'

export default Vue.extend({
  name: 'AppHeader',
  components: {
    BreadCrumb
  },
  data () {
    return {
      userInfo: {
        userName: '张三',
        portrait: '11122'
      } // 当前登录用户信息
    }
  },
  created () {
  },
  methods: {
    handleLogout () {
      this.$confirm('确认退出吗?', '退出提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => { // 确认执行这里
        // 清除登录状态
        this.$store.dispatch('FedLogOut')

        // 跳转到登录页面
        this.$router.push({
          name: 'login'
        })

        this.$message({
          type: 'success',
          message: '退出成功!'
        })
      }).catch(() => { // 取消执行这里
        this.$message({
          type: 'info',
          message: '已取消退出'
        })
      })
    }
  }
})
</script>

<style lang="scss" scoped>
.header {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  .el-dropdown-link {
    display: flex;
    align-items: center;
  }
}
</style>

SideBar页面

<template>
  <div class="aside">
    <el-menu
      default-active="4"
      @open="handleOpen"
      @close="handleClose"
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b"
      router
    >
      <el-submenu index="1">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span>权限管理</span>
        </template>
        <el-menu-item index="/auth/role">
          <i class="el-icon-setting"></i>
          <span slot="title">角色管理</span>
        </el-menu-item>
        <el-menu-item index="/auth/menu">
          <i class="el-icon-setting"></i>
          <span slot="title">菜单管理</span>
        </el-menu-item>
        <el-menu-item index="/auth/resource">
          <i class="el-icon-setting"></i>
          <span slot="title">资源管理</span>
        </el-menu-item>
      </el-submenu>
      <el-menu-item index="/demo">
        <i class="el-icon-menu"></i>
        <span slot="title">demo</span>
      </el-menu-item>
      <el-menu-item index="/user/index">
        <i class="el-icon-document"></i>
        <span slot="title">用户管理</span>
      </el-menu-item>
      <el-submenu index="4">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span>列表管理</span>
        </template>
        <el-menu-item index="/list/demo2">
          <i class="el-icon-setting"></i>
          <span slot="title">demo2</span>
        </el-menu-item>
        <el-menu-item index="/list/demo3">
          <i class="el-icon-setting"></i>
          <span slot="title">demo3</span>
        </el-menu-item>
      </el-submenu>
    </el-menu>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  name: 'AppAside',
  methods: {
    handleOpen (key) {
      console.log(key)
    },

    handleClose (key, keyPath) {
      console.log(key, keyPath)
    }
  }
})
</script>

<style lang="scss" scoped>
.aside {
  .el-menu {
    min-height: 100vh;
  }
}
</style>

在组件中新建index.js导出各个模块

export { default as NavBar } from './NavBar'
export { default as SideBar } from './SideBar'

最终成型

image.png

git 地址 gitee.com/zhangke153/…