【前端】Vue+Element UI案例:通用后台管理系统-代码总结
创始人
2024-01-27 13:47:32
0

文章目录

    • 前言
    • 项目文件目录
    • api
      • mockServe
        • home.js
        • permission.js
      • index.js
      • mock.js
      • user.js
    • assert
    • components
      • CommonAside.vue
      • CommonHeader.vue
      • CommonTags.vue
    • data
      • echartsData
        • order.js
        • user.js
        • video.js
      • mockData
        • tableData.js
        • userData.js
        • videoData.js
      • CountData.js
      • MenuData.js
      • TableData.js
      • TableLabel.js
    • router
      • index.js
    • store
      • index.js
      • tab.js
    • utils
      • request.js
    • Views
      • Home.vue
      • Login.vue
      • Main.vue
      • Mall.vue
      • PageOne.vue
      • PageTwo.vue
      • User.vue
    • App.vue
    • main.js
    • 要安装的依赖

前言

本来不打算用博客的方式记录代码的,想用git把它上传到代码仓库。但是由于对git的使用不太熟悉,把写得完善的项目代码初始化掉了!!非常崩溃…后来废了很大力气才把代码找回来。

为了以后把代码搞丢后还能找回来,还是要写个博客来记录一下代码。

项目链接:https://pan.baidu.com/s/1fTh4m_OkqV2PIuWdCgE-QQ
提取码:35sv

项目文件目录

在这里插入图片描述

api

在这里插入图片描述

mockServe

home.js

// mock数据模拟
import Mock from 'mockjs'
// 导入数据
import videoData from '../../data/mockData/videoData'
import userData from '../../data/mockData/userData'
import tableData from '../../data/mockData/tableData'// 图表数据
let List =[]
// 直接导出
export default {getStatisticalData: () => {//Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位for (let i = 0; i < 7; i++) {List.push(Mock.mock({苹果: Mock.Random.float(100, 8000, 0, 0),vivo: Mock.Random.float(100, 8000, 0, 0),oppo: Mock.Random.float(100, 8000, 0, 0),魅族: Mock.Random.float(100, 8000, 0, 0),三星: Mock.Random.float(100, 8000, 0, 0),小米: Mock.Random.float(100, 8000, 0, 0)}))}// 返回给浏览器的数据return {code: 20000,data: {// 饼图videoData,// 柱状图userData,// 折线图orderData: {date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],data: List},tableData}}}
}

permission.js

import Mock from 'mockjs'
export default {getMenu: config => {const { username, password } = JSON.parse(config.body)// 先判断用户是否存在// 判断账号和密码是否对应if (username === 'admin' && password === 'admin') {return {code: 20000,data: {menu: [{path: '/home',name: 'home',label: '首页',icon: 's-home',url: 'Home.vue'},{path: '/mall',name: 'mall',label: '商品管理',icon: 'video-play',url: 'Mall.vue'},{path: '/user',name: 'user',label: '用户管理',icon: 'user',url: 'User.vue'},{label: '其他',icon: 'location',children: [{path: '/page1',name: 'page1',label: '页面1',icon: 'setting',url: 'PageOne.vue'},{path: '/page2',name: 'page2',label: '页面2',icon: 'setting',url: 'PageTwo.vue'}]}],token: Mock.Random.guid(),message: '获取成功'}}} else if (username === 'xiaoxiao' && password === 'xiaoxiao') {return {code: 20000,data: {menu: [{path: '/home',name: 'home',label: '首页',icon: 's-home',url: 'Home.vue'},{path: '/video',name: 'video',label: '商品管理',icon: 'video-play',url: 'Mall.vue'}],token: Mock.Random.guid(),message: '获取成功'}}} else {return {code: -999,data: {message: '密码错误'}}}}
}

index.js

import http from '../utils/request'// 请求首页数据,直接把这个对象导出
export const getData = () => {// 返回一个promisereturn http.get('/home/getData')
}// 下面四个:用户管理-后端-网络请求接口
export const getUser = (params) => {return http.get('/user/get/', params)
}export const createUser = (data) => {return http.post('/user/create', data)
}export const deleteUser = (data) => {return http.post('/user/del', data)
}export const updateUser = (data) => {return http.post('/user/update', data)
}// 登录权限
export const getMenu = (data) => {return http.post('/permission/getMenu',data)
}

mock.js

import Mock from 'mockjs'
import homeMock from '../api/mockServe/home'
import user from './user'
import permission from './mockServe/permission'// 定义mock拦截
Mock.mock('/api/home/getData',homeMock)// 用户管理:增删查改
Mock.mock(/\/api\/user\/get/,user.getUserList)
Mock.mock('/api/user/create','post',user.createUser)
Mock.mock('/api/user/update','post',user.updateUser)
Mock.mock('/api/user/del','post',user.deleteUser)// 登录权限
Mock.mock(/api\/permission\/getMenu/,'post',permission.getMenu)

user.js

import Mock from 'mockjs'// get请求从config.url获取参数,post从config.body中获取参数
function param2Obj (url) {const search = url.split('?')[1]if (!search) {return {}}return JSON.parse('{"' +decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') +'"}')
}let List = []
const count = 200for (let i = 0; i < count; i++) {List.push(Mock.mock({id: Mock.Random.guid(),name: Mock.Random.cname(),addr: Mock.mock('@county(true)'),'age|18-60': 1,birth: Mock.Random.date(),sex: Mock.Random.integer(0, 1)}))
}export default {/*** 获取列表* 要带参数 name, page, limt; name可以不填, page,limit有默认值。* @param name, page, limit* @return {{code: number, count: number, data: *[]}}*/getUserList: config => {const { name, page = 1, limit = 20 } = param2Obj(config.url)// console.log('name:' + name, 'page:' + page, '分页大小limit:' + limit)const mockList = List.filter(user => {if (name && user.name.indexOf(name) === -1 && user.addr.indexOf(name) === -1) return falsereturn true})const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))return {code: 20000,count: mockList.length,list: pageList}},/*** 增加用户* @param name, addr, age, birth, sex* @return {{code: number, data: {message: string}}}*/createUser: config => {const { name, addr, age, birth, sex } = JSON.parse(config.body)console.log(JSON.parse(config.body))List.unshift({id: Mock.Random.guid(),name: name,addr: addr,age: age,birth: birth,sex: sex})return {code: 20000,data: {message: '添加成功'}}},/*** 删除用户* @param id* @return {*}*/deleteUser: config => {const { id } = JSON.parse(config.body)if (!id) {return {code: -999,message: '参数不正确'}} else {List = List.filter(u => u.id !== id)return {code: 20000,message: '删除成功'}}},/*** 批量删除* @param config* @return {{code: number, data: {message: string}}}*/batchremove: config => {let { ids } = param2Obj(config.url)ids = ids.split(',')List = List.filter(u => !ids.includes(u.id))return {code: 20000,data: {message: '批量删除成功'}}},/*** 修改用户* @param id, name, addr, age, birth, sex* @return {{code: number, data: {message: string}}}*/updateUser: config => {const { id, name, addr, age, birth, sex } = JSON.parse(config.body)const sex_num = parseInt(sex)List.some(u => {if (u.id === id) {u.name = nameu.addr = addru.age = ageu.birth = birthu.sex = sex_numreturn true}})return {code: 20000,data: {message: '编辑成功'}}}
}

assert

这些图片在链接里:

在这里插入图片描述

components

在这里插入图片描述

CommonAside.vue


CommonHeader.vue


CommonTags.vue


data

在这里插入图片描述

echartsData

order.js

const order = {legend: {// 图例文字颜色textStyle: {color: "#333",},},grid: {left: "20%",},// 提示框tooltip: {trigger: "axis",},xAxis: {type: "category", // 类目轴data: [],axisLine: {lineStyle: {color: "#17b3a3",},},axisLabel: {interval: 0,color: "#333",},},yAxis: [{type: "value",axisLine: {lineStyle: {color: "#17b3a3",},},},],color: ["#2ec7c9", "#b6a2de", "#5ab1ef", "#ffb980", "#d87a80", "#8d98b3"],series: [],
}export default order

user.js

const user = {legend: {// 图例文字颜色textStyle: {color: "#333",},},grid: {left: "20%",},// 提示框tooltip: {trigger: "axis",},xAxis: {type: "category", // 类目轴data: [],axisLine: {lineStyle: {color: "#17b3a3",},},axisLabel: {interval: 0,color: "#333",},},yAxis: [{type: "value",axisLine: {lineStyle: {color: "#17b3a3",},},},],color: ["#2ec7c9", "#b6a2de"],series: [],
}export default user

video.js

const video = {tooltip: {trigger: "item",},color: ["#0f78f4","#dd536b","#9462e5","#a6a6a6","#e1bb22","#39c362","#3ed1cf",],series: [],
}export default video

mockData

tableData.js

const tableData = [{name: 'oppo',todayBuy: 500,monthBuy: 3500,totalBuy: 22000},{name: 'vivo',todayBuy: 300,monthBuy: 2200,totalBuy: 24000},{name: '苹果',todayBuy: 800,monthBuy: 4500,totalBuy: 65000},{name: '小米',todayBuy: 1200,monthBuy: 6500,totalBuy: 45000},{name: '三星',todayBuy: 300,monthBuy: 2000,totalBuy: 34000},{name: '魅族',todayBuy: 350,monthBuy: 3000,totalBuy: 22000}
]export default tableData

userData.js

// 柱状图
const userData = [{date: '周一',new: 5,active: 200},{date: '周二',new: 10,active: 500},{date: '周三',new: 12,active: 550},{date: '周四',new: 60,active: 800},{date: '周五',new: 65,active: 550},{date: '周六',new: 53,active: 770},{date: '周日',new: 33,active: 170}
]export default userData

videoData.js

// 饼图
const videoData = [{name: '小米',value: 2999},{name: '苹果',value: 5999},{name: 'vivo',value: 1500},{name: 'oppo',value: 1999},{name: '魅族',value: 2200},{name: '三星',value: 4500}
]export default videoData

CountData.js

const CountData = [{name: "今日支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "今日收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "今日未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},{name: "本月支付订单",value: 1234,icon: "success",color: "#2ec7c9",},{name: "本月收藏订单",value: 210,icon: "star-on",color: "#ffb980",},{name: "本月未支付订单",value: 1234,icon: "s-goods",color: "#5ab1ef",},
]
export default CountData

MenuData.js

const MenuData= [{path: '/',name: 'home',label: '首页',icon: 's-home',url: 'Home/Home'},{path: '/mall',name: 'mall',label: '商品管理',icon: 'video-play',url: 'MallManage/MallManage'},{path: '/user',name: 'user',label: '用户管理',icon: 'user',url: 'UserManage/UserManage'},{label: '其他',icon: 'location',children: [{path: '/page1',name: 'page1',label: '页面1',icon: 'setting',url: 'Other/PageOne'},{path: '/page2',name: 'page2',label: '页面2',icon: 'setting',url: 'Other/PageTwo'}]}
]export default MenuData

TableData.js

const TableData = [{name: 'oppo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: 'vivo',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '苹果',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '小米',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '三星',todayBuy: 100,monthBuy: 300,totalBuy: 800},{name: '魅族',todayBuy: 100,monthBuy: 300,totalBuy: 800}
]export default TableData

TableLabel.js

const TableLabel={name:'课程',todayBuy:'今日购买',monthBuy:'本月购买',totalBuy:'总购买'
}export default TableLabel

router

在这里插入图片描述

index.js

import Vue from "vue";
import VueRouter from "vue-router";
import Main from '../Views/Main'
// import Home from '../Views/Home.vue'
// import Mall from '../Views/Mall.vue'
// import User from '../Views/User.vue'
// import PageOne from '../Views/PageOne.vue'
// import PageTwo from '../Views/PageTwo.vue'
import Login from '../Views/Login.vue'
import Cookie from 'js-cookie'Vue.use(VueRouter)const routes = [// 主路由{path: '/',name:'Main',component: Main,redirect: '/home', // 重定向children: [// 子路由// { path: '/home', name: 'home', component: Home }, // 首页// { path: '/user', name: 'user', component: User }, // 用户管理// { path: '/mall', name: 'mall', component: Mall }, // 商品管理// { path: '/page1', name: 'page1', component: PageOne }, // 页面1// { path: '/page2', name: 'page2', component: PageTwo }, // 页面2]},{path: '/login',name: 'login',component: Login}
]const router = new VueRouter({routes
})// 路由守卫:全局前置导航守卫
router.beforeEach((to, from, next) => {// 获取tokenconst token = Cookie.get('token')if (!token && to.name !== 'login') {next({ name: 'login' })} else if (token && to.name === 'login') {next({ name: 'home' })} else {next()}
})export default router

store

在这里插入图片描述

index.js

import Vue from "vue";
import Vuex from 'vuex';
import tab from './tab';Vue.use(Vuex)// 创建Vuex实例并导出
export default new Vuex.Store({modules:{tab}
})

tab.js

import Cookie from "js-cookie"export default {state: {isCollapse: false,//导航栏是否折叠tabList: [{path: '/',name: 'home',label: '首页',icon: 's-home',url: 'Home/Home'}],//面包屑的数据:点了哪个路由,首页是一定有的menu: [],//不同用户的菜单},mutations: {// 修改导航栏展开和收起的方法CollapseMenu(state) {state.isCollapse = !state.isCollapse},// 更新面包屑的数据SelectMenu(state, item) {// 如果点击的不在面包屑数据中,则添加const index = state.tabList.findIndex(val => val.name === item.name)if (index === -1) {state.tabList.push(item)}},// 删除tag:删除tabList中对应的itemcloseTag(state, item) {// 要删除的是state.tabList中的itemconst index = state.tabList.findIndex(val => val.name === item.name)state.tabList.splice(index, 1)},// 设置不同用户的菜单setMenu(state, val) {state.menu = valCookie.set('menu', JSON.stringify(val))},// 动态添加路由addMenu(state, router) {// 判断Cookieif (!Cookie.get('menu')) returnconst menu = JSON.parse(Cookie.get('menu'))state.menu = menuconst menuArray = []// 组装路由menu.forEach(item => {// 判断是否有子路由if (item.children) {item.children = item.children.map(itemm => {itemm.component = () => import(`../Views/${itemm.url}`)return itemm})menuArray.push(...item.children)} else {item.component = () => import(`../Views/${item.url}`)menuArray.push(item)}});console.log(menuArray, 'menuArray');menuArray.forEach(item => {router.addRoute('Main', item)})}}
}

utils

在这里插入图片描述

request.js

import axios from "axios";// 封装一个axios实例
const http = axios.create({// 通用请求的地址前缀baseURL: '/api',// 超时时间timeout: 100000
})// 请求拦截器
http.interceptors.request.use(function (config) {// 在发送请求之前做什么return config;
}, function (error) {// 对请求错误做什么return Promise.reject(error);
})// 添加响应拦截器
http.interceptors.response.use(function (response) {// 对响应数据做什么return response;
}, function (error) {// 对响应错误做什么return Promise.reject(error);
})export default http

Views

在这里插入图片描述

Home.vue


Login.vue


Main.vue

Mall.vue


PageOne.vue


PageTwo.vue


User.vue


App.vue


main.js

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
import router from './router/index'
import store from './store/index'
import './api/mock'Vue.config.productionTip = false
Vue.use(ElementUI)new Vue({router,store,render: h => h(App),created() {store.commit('addMenu', router)}
}).$mount('#app')

要安装的依赖

"dependencies": {"axios": "^1.1.3","core-js": "^3.8.3","echarts": "^5.1.2","element-ui": "^2.15.10","js-cookie": "^3.0.1","less": "^4.1.3","less-loader": "^11.1.0","mockjs": "^1.1.0","vue": "^2.6.14","vue-router": "^3.6.5","vuex": "^3.6.2"}

相关内容

热门资讯

小本项目万元就可以创业 小本项... 只要者能准确选取万元,把握好经营方向,做好创业者应有的心态,小本创业仍旧可以以小搏大,成就大事业。下...
小本万元创业项目 小本万元创业... 不管一万元最后投资的创业项目是什么,最主要的还是利润和受益。以下是小编给大家带来,以供参阅。  万元...
【活动回顾】我为创业狂第一季初... 特邀嘉宾活动邀请了拉尔夫创投合伙人陈冬华、东南大学教授陈国庆、博峻汇屈伯骏、邦宁资本陈普作为评委嘉宾...
没有钱怎么创业 没有钱怎么创业 2.借开店人的货,为自己赚钱。朋友开了一个鸭脖子店,但是没有开1个月,因为没有可观的人流量,于是以失...
大学生创业点子创业点子吧有哪些... 很多大学生在大学的时候就想开始创业,想创业是好事儿,起码是自主解决就业的一种自食其力的方式。但创业不...
有什么好的在家创业的小本项目 ... 有什么好的在家创业的小本项目!人人都可做的。现在很多家庭,都面对着经济上支出的压力,出门在外的父母们...
最适合年轻人的15个小本创业项...   网上开店IT行业现在不少学生创业从电子商务起步,好处是成本低---网上开店是免费的;门槛低---...
对口援疆 潮涌天山丨漳木一家亲...   在天山北麓的木垒大地,福建省对口支援新疆工作前方指挥部漳州分指挥部(以下简称“漳州分指”)完整准...
上合之约:带你领略天津之美   7月8日,以“开放包容 融合发展”为主题的“世界市长对话•上合峰会城市”活动将在天津举行。当无人...
一手对14国加税 一手延长暂缓...   当地时间7日,美国总统特朗普发信函给日韩及南非等14国威胁征税,随后,他又签署行政令,延长“对等...