目录
前言
总结
前言
随着软件开发不断进步,前后端框架技术也取得重大进步,前端主要有Layui经典框架,还有谷歌flutter和如今流行的Vue框架,后端主要有Spring框架,尤其是SpringBoot应用非常广泛,而前端这门技术也越来越重要,很多人都开启了学习Vue技术,本文就介绍了Vue的基础内容以及后台管理系统项目分享。
一、Vue是什么?
Vue 是一种流行的轻量级JavaScript 框架,用于构建用户界面和单页面应用程序。Vue 由 Evan You 创建,并于 2014 年首次发布,其主要开源者是曾经谷歌前端开发人员尤雨溪。Vue 的设计目标是简单、灵活和易于使用,同时具有高性能和可扩展性。
Vue 使用声明式渲染和组件化架构来使开发人员可以将应用程序拆分为多个小组件,并由组件组成模块,极大地降低开发复杂度,减轻前端开发人员工作难度,并将其组合在一起构建复杂的用户界面。Vue 还提供了一组工具和插件,使开发人员可以更轻松地管理应用程序的状态和路由,同时支持动态加载和懒加载。
Vue 还提供了大量的文档和教程,可以说Vue的生态领域发展非常完善,并且目前版本已经更新到Vue3.0,是一个活跃的社区,使其成为开发人员喜欢的框架之一。
二、Vue使用步骤
- 使用 Vue.js 构建应用程序可以遵循以下步骤:(这里我们使用VScode)
- 安装 Vue.js:首先需要安装 Vue.js。可以使用 npm 或 yarn 进行安装。
- 创建 Vue 实例:在文件中创建 Vue 实例,通常在 index.html 或 webpack.config.js 中设置。
- 创建组件:创建组件,并在组件中定义数据、方法、生命周期钩子等。组件可以是公共组件或私有组件。
- 组件通信:组件之间需要进行通信,可以使用 Vuex、Vue Router 等状态管理和路由管理工具。
- 创建路由:创建路由,并在路由中定义导航守卫、动态路由等。
- 创建动态加载:使用 Vue Router 的动态加载功能,将数据加载到应用程序中。
- 创建懒加载:使用 Vuex 或其他状态管理工具实现懒加载,只在需要时才加载数据。
- 编写测试:编写单元测试和集成测试来验证组件和应用程序的性能和功能。
- 维护和维护:定期维护和更新应用程序,确保其正常运行并保持最新状态。
- 以上是使用 Vue.js 构建应用程序的基本步骤。当然,在实际开发中,需要根据具体需求进行调整和优化。
三 、重点讲解如何搭建完整后台管理系统
本项目主要通过Vue2.0来搭建的管理系统,此外我使用ElementUi组件库+webpack + ES6/7 + axios等技术,其主要实现功能如下所示:
- 登录验证
- 路由拦截
- 公司管理
- 订单交易
- 商品管理
- 角色管理
- 系统管理
- 支付管理
- 用户管理
- 支付配置
- 大数据图表
- 系统环境变量
- 权限管理
- 菜单管理
- 个人中心
主要管理页面展示
登录页面
大数据页面
四、主要源码分享
1、显示出错组件
/**
* 404
*/
<template>
<div class="page-404">
<h1>404!</h1>
<h2>Sorry, page not found</h2>
</div>
</template>
<style scoped>
.page-404 {
text-align: center;
}
.page-404 h1 {
font-size: 98px;
font-weight: 700;
line-height: 150px;
text-shadow: rgba(61, 61, 61, 0.3) 1px 1px, rgba(61, 61, 61, 0.2) 2px 2px,
rgba(61, 61, 61, 0.3) 3px 3px;
}
.page-404 h2 {
line-height: 30px;
font-size: 30px;
}
</style>
2、左边菜单组件
<template>
<el-menu default-active="2" :collapse="collapsed" collapse-transition router :default-active="$route.path" unique-opened class="el-menu-vertical-demo" background-color="#334157" text-color="#fff" active-text-color="#ffd04b">
<div class="logobox">
<img class="logoimg" src="../assets/img/logo.png" alt="">
</div>
<el-submenu v-for="menu in allmenu" :key="menu.menuid" :index="menu.menuname">
<template slot="title">
<i class="iconfont" :class="menu.icon"></i>
<span>{{menu.menuname}}</span>
</template>
<el-menu-item-group>
<el-menu-item v-for="chmenu in menu.menus" :index="'/'+chmenu.url" :key="chmenu.menuid">
<i class="iconfont" :class="chmenu.icon"></i>
<span>{{chmenu.menuname}}</span>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</template>
<script>
import { menu } from '../api/userMG'
export default {
name: 'leftnav',
data() {
return {
collapsed: false,
allmenu: []
}
},
// 创建完毕状态(里面是操作)
created() {
// 获取图形验证码
let res = {
success: true,
data: [
{
menuid: 1,
icon: 'li-icon-xiangmuguanli',
menuname: '公司管理',
hasThird: null,
url: null,
// 多级路由嵌套
menus: [
{
menuid: 2,
icon: 'icon-cat-skuQuery',
menuname: '商品销售',
hasThird: 'N',
url: 'goods/Goods',
menus: null
}
]
},
{
menuid: 33,
icon: 'li-icon-dingdanguanli',
menuname: '订单交易',
hasThird: null,
url: null,
menus: [
{
menuid: 34,
icon: 'icon-order-manage',
menuname: '交易订单',
hasThird: 'N',
url: 'pay/Order',
menus: null
}
]
},
{
menuid: 71,
icon: 'li-icon-xitongguanli',
menuname: '系统管理',
hasThird: null,
url: null,
menus: [
{
menuid: 72,
icon: 'icon-cus-manage',
menuname: '用户管理',
hasThird: 'N',
url: 'system/user',
menus: null
},
{
menuid: 174,
icon: 'icon-cms-manage',
menuname: '菜单管理',
hasThird: 'N',
url: 'system/Module',
menus: null
},
{
menuid: 73,
icon: 'icon-news-manage',
menuname: '角色管理',
hasThird: 'N',
url: 'system/Role',
menus: null
},
{
menuid: 74,
icon: 'icon-cs-manage',
menuname: '公司管理',
hasThird: 'N',
url: 'system/Dept',
menus: null
},
{
menuid: 75,
icon: 'icon-promotion-manage',
menuname: '系统环境变量',
hasThird: 'N',
url: 'system/Variable',
menus: null
},
{
menuid: 76,
icon: 'icon-cms-manage',
menuname: '权限管理',
hasThird: 'N',
url: 'system/Permission',
menus: null
}
]
},
{
menuid: 128,
icon: 'li-icon-shangchengxitongtubiaozitihuayuanwenjian91',
menuname: '支付管理',
hasThird: null,
url: null,
menus: [
{
menuid: 129,
icon: 'icon-provider-manage',
menuname: '支付配置信息',
hasThird: 'N',
url: 'machine/MachineConfig',
menus: null
},
{
menuid: 175,
icon: 'icon-provider-manage',
menuname: '支付配置',
hasThird: 'N',
url: 'pay/Config',
menus: null
}
]
},
{
menuid: 150,
icon: 'li-icon-shangchengxitongtubiaozitihuayuanwenjian91',
menuname: '图表',
hasThird: null,
url: null,
menus: [
{
menuid: 159,
icon: 'icon-provider-manage',
menuname: '数据可视化',
hasThird: 'N',
url: 'charts/statistics',
menus: null
}
]
}
],
msg: 'success'
}
this.allmenu = res.data
menu(localStorage.getItem('logintoken'))
.then(res => {
console.log(JSON.stringify(res))
if (res.success) {
this.allmenu = res.data
} else {
this.$message.error(res.msg)
return false
}
})
.catch(err => {
this.$message.error('菜单加载失败,请稍后再试!')
})
监听
this.$root.Bus.$on('toggle', value => {
this.collapsed = !value
})
}
}
</script>
<style>
.el-menu-vertical-demo:not(.el-menu--collapse) {
width: 240px;
min-height: 400px;
}
.el-menu-vertical-demo:not(.el-menu--collapse) {
border: none;
text-align: left;
}
.el-menu-item-group__title {
padding: 0px;
}
.el-menu-bg {
background-color: #1f2d3d !important;
}
.el-menu {
border: none;
}
.logobox {
height: 40px;
line-height: 40px;
color: #9d9d9d;
font-size: 20px;
text-align: center;
padding: 20px 0px;
}
.logoimg {
height: 40px;
}
</style>
3、导航区组件
/**
* 头部菜单 这个组件就是导航区
*/
<template>
<el-menu class="el-menu-demo" mode="horizontal" background-color="#334157" text-color="#fff" active-text-color="#fff">
<el-button class="buttonimg">
<img class="showimg" :src="collapsed?imgsq:imgshow" @click="toggle(collapsed)">
</el-button>
<el-submenu index="2" class="submenu">
<!-- <template slot="title">{{user.userRealName}}</template> -->
<template slot="title">个人信息中心</template>
<el-menu-item index="2-1">set</el-menu-item>
<el-menu-item @click="content()" index="2-2">person</el-menu-item>
<el-menu-item @click="exit()" index="2-3">exit</el-menu-item>
</el-submenu>
</el-menu>
</template>
<script>
import { loginout } from '../api/userMG'
export default {
name: 'navcon',
data() {
return {
collapsed: true,
imgshow: require('../assets/img/show.png'),
imgsq: require('../assets/img/sq.png'),
user: {}
}
},
// 创建完毕状态(里面是操作)
created() {
this.user = JSON.parse(localStorage.getItem('userdata'))
},
methods: {
// 退出登录
exit() {
this.$confirm('退出登录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
setTimeout(() => {
this.$store.commit('logout', 'false')
this.$router.push({ path: '/login' })
this.$message({
type: 'success',
message: '已退出登录!'
})
}, 1000)
loginout()
.then(res => {
if (res.success) {
//如果请求成功就让他2秒跳转路由
setTimeout(() => {
this.$store.commit('logout', 'false')
this.$router.push({ path: '/login' })
this.$message({
type: 'success',
message: '已退出登录!'
})
}, 1000)
} else {
this.$message.error(res.msg)
this.logining = false
return false
}
})
.catch(err => {
// 获取图形验证码
this.getcode()
this.logining = false
this.$message.error('退出失败,请稍后再试!')
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消'
})
})
},
// 切换显示
toggle(showtype) {
this.collapsed = !showtype
this.$root.Bus.$emit('toggle', this.collapsed)
}
}
}
</script>
<style scoped>
.el-menu-vertical-demo:not(.el-menu--collapse) {
border: none;
}
.submenu {
float: right;
}
.buttonimg {
height: 60px;
background-color: transparent;
border: none;
}
.showimg {
width: 26px;
height: 26px;
position: absolute;
top: 17px;
left: 17px;
}
.showimg:active {
border: none;
}
</style>
4、分页组件(主要是切换右下角不同组件)
<template>
<el-pagination class="page-box" @size-change="handleSizeChange" @current-change="handleCurrentChange" background :current-page="childMsg.currentPage" :page-sizes="[10, 20, 30, 40]" :page-size="childMsg.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="childMsg.total">
</el-pagination>
</template>
<script>
export default {
name: 'Pagination',
props: ['childMsg'],
data() {
return {
pageparm: {
currentPage: this.childMsg.currentPage,
pageSize: this.childMsg.pageSize
}
}
},
created() {},
methods: {
handleSizeChange(val) {
this.pageparm.pageSize = val
this.$emit('callFather', this.pageparm)
},
handleCurrentChange(val) {
this.pageparm.currentPage = val
this.$emit('callFather', this.pageparm)
}
}
}
</script>
<style>
.page-box {
margin: 10px auto;
}
</style>
5、模板组件
<template>
<div>
</div>
</template>
<script>
import headerComponent from "./head.vue";
export default {
name: "template",
data() {
return {};
},
components: {
headerComponent
},
watch: {},
methods: {
addFun() {},
submitFun() {}
},
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeDestroy() {},
destroyed() {}
};
</script>
<style scoped>
</style>
6、主要视图组件
大数据可视化页面组件
<template>
<!-- 组件主盒子 -->
<div class="stbox">
<!-- 面包屑导航 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>数据可视化</el-breadcrumb-item>
</el-breadcrumb>
<!-- 搜索,切换 -->
<el-row :gutter="23">
<el-col :span="18">
<div class="stbgc">
<el-row :gutter="23">
<el-col :span="7">
<el-input size="small" v-model="machineNo" placeholder="请输入所属公司"></el-input>
</el-col>
<el-col :span="7">
<el-input size="small" v-model="machineNo" placeholder="请输入资产编号"></el-input>
</el-col>
<el-col :span="7">
<el-input size="small" v-model="machineNo" placeholder="请输入"></el-input>
</el-col>
<el-col :span="3" class="stsearch">
<el-button size="small" type="primary">搜索</el-button>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="6">
<div class="stbgc">
<el-row>
<el-col :span="8" class="text-c">
<el-radio v-model="type" label="day">日</el-radio>
</el-col>
<el-col :span="8" class="text-c">
<el-radio v-model="type" label="month">月</el-radio>
</el-col>
<el-col :span="8" class="text-c">
<el-radio v-model="type" label="years">年</el-radio>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<!-- 统计图 -->
<el-row :gutter="23">
<el-col :span="8" class="text-c">
<div class="st-gbox">
<div class="cavasbox" ref="SCEchart"></div>
</div>
</el-col>
<el-col :span="8" class="text-c">
<div class="st-gbox">
<div class="cavasbox" ref="SUMEchart"></div>
</div>
</el-col>
<el-col :span="8" class="text-c">
<div class="st-gbox">
<div class="cavasbox" ref="ClickEchart"></div>
</div>
</el-col>
</el-row>
<!-- 统计图 -->
<div>
<el-row :gutter="23">
<el-col :span="12" class="text-c">
<div class="paybox">
<div class="cavasbox" ref="payEchart"></div>
</div>
</el-col>
<el-col :span="12" class="text-c">
<div class="paybox">
<div class="cavasbox" ref="payNumEchart"></div>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import Chart from 'echarts'
export default {
name: "welcome",
data() {
return {
machineNo: '',
type: 'day',
// 销售总笔数
SCEoption: {
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}月 : {c}"
},
legend: {
data: [{
name: '销售总笔数',
icon: 'rect'
}],
top: 1,
left: 1,
itemGap: 10,
itemWidth: 12,
itemHeight: 12,
textStyle: {
fontSize: 12,
color: "#323232"
}
},
grid: {
left: 50,
right: 10,
top: 30,
bottom: 30,
borderWidth: 1
},
xAxis: {
type: 'category',
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
height: 70,
interval: 0,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
series: [{
name: '销售总笔数',
type: 'bar',
barGap: 0,
data: [50000, 70000, 80000, 40000, 50000, 30000, 40000, 60000, 50000, 40000, 60000, 40000],
barWidth: 10,
itemStyle: {
normal: {
color: new Chart.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
]
)
},
emphasis: {
color: new Chart.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#2378f7' },
{ offset: 0.7, color: '#2378f7' },
{ offset: 1, color: '#83bff6' }
]
)
}
}
}]
},
// 销售总金额
SUMoption: {
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}月 : {c}"
},
legend: {
data: [{
name: '销售总金额',
icon: 'rect'
}],
top: 1,
left: 1,
itemGap: 10,
itemWidth: 12,
itemHeight: 12,
textStyle: {
fontSize: 12,
color: "#323232"
}
},
grid: {
left: 50,
right: 10,
top: 30,
bottom: 30,
borderWidth: 1
},
xAxis: {
type: 'category',
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
height: 70,
interval: 0,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
series: [{
name: '销售总金额',
// type: 'bar',
type: 'line',
barGap: 0,
data: [50000, 70000, 80000, 40000, 50000, 30000, 40000, 60000, 50000, 40000, 60000, 40000],
barWidth: 10,
itemStyle: {
color: "#108ff9"
}
}]
},
// 总点击量
Clickoption: {
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}月 : {c}"
},
legend: {
data: [{
name: '总点击量',
icon: 'rect'
}],
top: 1,
left: 1,
itemGap: 10,
itemWidth: 12,
itemHeight: 12,
textStyle: {
fontSize: 12,
color: "#323232"
}
},
grid: {
left: 50,
right: 10,
top: 30,
bottom: 30,
borderWidth: 1
},
xAxis: {
type: 'category',
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
height: 70,
interval: 0,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: "#999999",
width: 1
}
},
axisLabel: {
margin: 14,
textStyle: {
fontSize: 10,
color: "#999999"
}
}
},
series: [{
name: '总点击量',
type: 'bar',
barGap: 0,
data: [50000, 10000, 80000, 30000, 50000, 60000, 40000, 80000, 50000, 20000, 60000, 40000],
barWidth: 10,
itemStyle: {
color: "#48cefd"
}
}]
},
// 支付方式统计
payoption: {
backgroundColor: '#2c343c',
title: {
text: '支付方式统计(金额)',
left: 10,
top: 5,
textStyle: {
fontSize: 12,
color: '#ccc'
}
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
visualMap: {
show: false,
min: 80,
max: 600,
inRange: {
colorLightness: [0, 1]
}
},
series: [
{
name: '支付方式统计(金额)',
type: 'pie',
radius: '55%',
center: ['50%', '50%'],
data: [
{ value: 335, name: '支付宝' },
{ value: 310, name: '银商二维码' },
{ value: 274, name: '会员' },
{ value: 235, name: '微信支付' },
{ value: 100, name: 'Pos通' }
].sort(function (a, b) { return a.value - b.value; }),
roseType: 'radius',
label: {
normal: {
textStyle: {
color: 'rgba(255, 255, 255, 0.3)'
}
}
},
labelLine: {
normal: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.3)'
},
smooth: 0.2,
length: 10,
length2: 20
}
},
itemStyle: {
normal: {
color: '#c23531',
shadowBlur: 200,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
animationType: 'scale',
animationEasing: 'elasticOut',
animationDelay: function (idx) {
return Math.random() * 200;
}
}
]
},
payNumoption: {
backgroundColor: '#2c343c',
title: {
text: '支付方式统计(笔数)',
left: 10,
top: 5,
textStyle: {
fontSize: 12,
color: '#ccc'
}
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
visualMap: {
show: false,
min: 80,
max: 600,
inRange: {
colorLightness: [0, 1]
}
},
series: [
{
name: '支付方式统计(笔数)',
type: 'pie',
radius: '55%',
center: ['50%', '50%'],
data: [
{ value: 335, name: '支付宝' },
{ value: 310, name: '银商二维码' },
{ value: 274, name: '会员' },
{ value: 235, name: '微信支付' },
{ value: 100, name: 'Pos通' }
].sort(function (a, b) { return a.value - b.value; }),
roseType: 'radius',
label: {
normal: {
textStyle: {
color: 'rgba(255, 255, 255, 0.3)'
}
}
},
labelLine: {
normal: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.3)'
},
smooth: 0.2,
length: 10,
length2: 20
}
},
itemStyle: {
normal: {
color: '#c23531',
shadowBlur: 200,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
},
animationType: 'scale',
animationEasing: 'elasticOut',
animationDelay: function (idx) {
return Math.random() * 200;
}
}
]
},
}
},
// 导入组件
components: {
// 点聚合组件
},
// 创建完毕状态(里面是操作)
created() { },
// 挂载结束状态(里面是操作)
mounted() {
this.getSCE()
this.getSUM()
this.getClick()
this.getpay()
this.getpayNum()
},
// 里面的函数只有调用才会执行
methods: {
// 交易总笔数
getSCE() {
this.chart = Chart.init(this.$refs.SCEchart)
this.chart.setOption(this.SCEoption)
},
// 交易总金额
getSUM() {
this.chart = Chart.init(this.$refs.SUMEchart)
this.chart.setOption(this.SUMoption)
},
// 总点击量
getClick() {
this.chart = Chart.init(this.$refs.ClickEchart)
this.chart.setOption(this.Clickoption)
},
// 支付方式统计
getpay() {
this.chart = Chart.init(this.$refs.payEchart)
this.chart.setOption(this.payoption)
},
// 支付方式统计
getpayNum() {
this.chart = Chart.init(this.$refs.payNumEchart)
this.chart.setOption(this.payNumoption)
}
}
};
</script>
<style>
.stbox {
width: 100%;
height: 100%;
box-sizing: border-box;
}
.stbgc {
background-color: #fff;
height: 60px;
line-height: 60px;
border-radius: 5px;
padding: 0px 16px;
}
.stsearch {
text-align: center;
}
.text-c {
text-align: center;
}
.st-gbox {
background-color: #fff;
margin-top: 20px;
border-radius: 5px;
height: 30vh;
box-sizing: border-box;
padding: 10px;
}
.cavasbox {
box-sizing: border-box;
width: 100%;
height: 100%;
}
.paybox {
width: 100%;
background-color: #fff;
box-sizing: border-box;
border-radius: 5px;
margin-top: 20px;
height: 32vh;
}
</style>
商品管理组件
<template>
<div>
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
</el-breadcrumb>
<el-form :inline="true" :model="formInline" class="user-search">
<el-form-item label="搜索:">
<el-input size="small" v-model="formInline.deptName" placeholder="输入部门名称"></el-input>
</el-form-item>
<el-form-item label="">
<el-input size="small" v-model="formInline.deptNo" placeholder="输入部门代码"></el-input>
</el-form-item>
<el-form-item>
<el-button size="small" type="primary" icon="el-icon-search" @click="search">搜索</el-button>
<el-button size="small" type="primary" icon="el-icon-plus" @click="handleEdit()">添加</el-button>
</el-form-item>
</el-form>
<!--列表-->
<el-table size="small" :data="listData" highlight-current-row v-loading="loading" border element-loading-text="拼命加载中" style="width: 100%;">
<el-table-column align="center" type="selection" width="60">
</el-table-column>
<el-table-column sortable prop="deptName" label="部门名称" width="300">
</el-table-column>
<el-table-column sortable prop="deptNo" label="部门代码" width="300">
</el-table-column>
<el-table-column sortable prop="editTime" label="修改时间" width="300">
<template slot-scope="scope">
<div>{{scope.row.editTime|timestampToTime}}</div>
</template>
</el-table-column>
<el-table-column sortable prop="editUser" label="修改人" width="300">
</el-table-column>
<el-table-column align="center" label="操作" min-width="300">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
<el-button size="mini" type="danger" @click="deleteUser(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<Pagination v-bind:child-msg="pageparm" @callFather="callFather"></Pagination>
<!-- 编辑界面 -->
<el-dialog :title="title" :visible.sync="editFormVisible" width="30%" @click="closeDialog">
<el-form label-width="120px" :model="editForm" :rules="rules" ref="editForm">
<el-form-item label="部门名称" prop="deptName">
<el-input size="small" v-model="editForm.deptName" auto-complete="off" placeholder="请输入部门名称"></el-input>
</el-form-item>
<el-form-item label="部门代码" prop="deptNo">
<el-input size="small" v-model="editForm.deptNo" auto-complete="off" placeholder="请输入部门代码"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="small" @click="closeDialog">取消</el-button>
<el-button size="small" type="primary" :loading="loading" class="title" @click="submitForm('editForm')">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { deptList, deptSave, deptDelete } from '../../api/userMG'
import Pagination from '../../components/Pagination'
export default {
data() {
return {
nshow: true, //switch开启
fshow: false, //switch关闭
loading: false, //是显示加载
editFormVisible: false, //控制编辑页面显示与隐藏
title: '添加',
editForm: {
deptId: '',
deptName: '',
deptNo: '',
token: localStorage.getItem('logintoken')
},
// rules表单验证
rules: {
deptName: [
{ required: true, message: '请输入部门名称', trigger: 'blur' }
],
deptNo: [{ required: true, message: '请输入部门代码', trigger: 'blur' }]
},
formInline: {
page: 1,
limit: 10,
varLable: '',
varName: '',
token: localStorage.getItem('logintoken')
},
// 删除部门
seletedata: {
ids: '',
token: localStorage.getItem('logintoken')
},
userparm: [], //搜索权限
listData: [], //用户数据
// 分页参数
pageparm: {
currentPage: 1,
pageSize: 10,
total: 10
}
}
},
// 注册组件
components: {
Pagination
},
/**
* 数据发生改变
*/
/**
* 创建完毕
*/
created() {
this.getdata(this.formInline)
},
/**
* 里面的方法只有被调用才会执行
*/
methods: {
// 获取公司列表
getdata(parameter) {
this.loading = true
// 模拟数据开始
let res = {
code: 0,
msg: null,
count: 5,
data: [
{
addUser: null,
editUser: null,
addTime: 1521062371000,
editTime: 1526700200000,
deptId: 2,
deptName: 'XX分公司',
deptNo: '1',
parentId: 1
},
{
addUser: null,
editUser: null,
addTime: 1521063247000,
editTime: 1526652291000,
deptId: 3,
deptName: '上海测试',
deptNo: '02',
parentId: 1
},
{
addUser: null,
editUser: null,
addTime: 1526349555000,
editTime: 1526349565000,
deptId: 12,
deptName: '1',
deptNo: '11',
parentId: 1
},
{
addUser: null,
editUser: null,
addTime: 1526373178000,
editTime: 1526373178000,
deptId: 13,
deptName: '5',
deptNo: '5',
parentId: 1
},
{
addUser: null,
editUser: null,
addTime: 1526453107000,
editTime: 1526453107000,
deptId: 17,
deptName: 'v',
deptNo: 'v',
parentId: 1
}
]
}
this.loading = false
this.listData = res.data
this.pageparm.currentPage = this.formInline.page
this.pageparm.pageSize = this.formInline.limit
this.pageparm.total = res.count
deptList(parameter)
.then(res => {
this.loading = false
if (res.success == false) {
this.$message({
type: 'info',
message: res.msg
})
} else {
this.listData = res.data
// 分页赋值
this.pageparm.currentPage = this.formInline.page
this.pageparm.pageSize = this.formInline.limit
this.pageparm.total = res.count
}
})
.catch(err => {
this.loading = false
this.$message.error('菜单加载失败,请稍后再试!')
})
},
callFather(parm) {
this.formInline.page = parm.currentPage
this.formInline.limit = parm.pageSize
this.getdata(this.formInline)
},
search() {
this.getdata(this.formInline)
},
handleEdit: function(index, row) {
this.editFormVisible = true
if (row != undefined && row != 'undefined') {
this.title = '修改'
this.editForm.deptId = row.deptId
this.editForm.deptName = row.deptName
this.editForm.deptNo = row.deptNo
} else {
this.title = '添加'
this.editForm.deptId = ''
this.editForm.deptName = ''
this.editForm.deptNo = ''
}
},
submitForm(editData) {
this.$refs[editData].validate(valid => {
if (valid) {
deptSave(this.editForm)
.then(res => {
this.editFormVisible = false
this.loading = false
if (res.success) {
this.getdata(this.formInline)
this.$message({
type: 'success',
message: '公司保存成功!'
})
} else {
this.$message({
type: 'info',
message: res.msg
})
}
})
.catch(err => {
this.editFormVisible = false
this.loading = false
this.$message.error('公司保存失败,请稍后再试!')
})
} else {
return false
}
})
},
// 删除公司
deleteUser(index, row) {
this.$confirm('确定要删除吗?', '信息', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(() => {
deptDelete(row.deptId)
.then(res => {
if (res.success) {
this.$message({
type: 'success',
message: '公司已删除!'
})
this.getdata(this.formInline)
} else {
this.$message({
type: 'info',
message: res.msg
})
}
})
.catch(err => {
this.loading = false
this.$message.error('公司删除失败,请稍后再试!')
})
})
.catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
closeDialog() {
this.editFormVisible = false
}
}
}
</script>
<style scoped>
.user-search {
margin-top: 20px;
}
.userRole {
width: 100%;
}
</style>
7、App.vue组件
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
export default {
name: "App"
};
</script>
<style>
html,
body {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0px;
margin: 0px;
}
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
widows: 100%;
height: 100%;
}
</style>
8、main.js(核心代码)
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App';
// 引入路由
import router from './router';
// 引入状态管理
import store from './vuex/store';
import './assets/icon/iconfont.css'
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
import axios from 'axios';
Vue.prototype.$axios = axios;
Vue.config.productionTip = false;
// 使用element UI
Vue.use(ElementUI);
import * as custom from './utils/util'
Object.keys(custom).forEach(key => {
Vue.filter(key, custom[key])
})
router.beforeEach((to, from, next) => {
if (to.matched.length != 0) {
if (to.meta.requireAuth) { // 判断该路由是否需要登录权限
if (Boolean(localStorage.getItem("userInfo"))) { // 通过vuex state获取当前的user是否存在
next();
} else {
next({
path: '/login',
query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
}
} else {
if (Boolean(localStorage.getItem("userInfo"))) { // 判断是否登录
if (to.path != "/" && to.path != "/login") { //判断是否要跳到登录界面
next();
} else {
/**
* 防刷新,如果登录,修改路由跳转到登录页面,修改路由为登录后的首页
*/
next({
path: '/goods/Goods'
})
}
} else {
next();
}
}
} else {
next({
path: '/login',
query: { redirect: to.fullPath } // 将跳转的路由path作为参数,登录成功后跳转到该路由
})
}
})
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>',
data: {
Bus: new Vue()
}
})
总结
以上就是今天要讲的内容,本文主要介绍了Vue的使用教程,并分享使用Vue搭建的后台商品管理系统,学好Vue技术对软件开发人员来说是非常重要的,不仅是因为Vue技术流行,并且Vue的生态技术比较完善,能够应用到不同场景,降低企业开发难度,极大地提高工作效率,Vue官方技术人员也在不断维护更新Vue技术,今天就介绍到这里了,希望能对大家有所帮助,喜欢的朋友请三连支持哦!更多优秀项目等着你哦!